diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..220c0db --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +################################################################################ +######################### User configurable parameters ######################### +# filename extensions +CEXTS:=c +ASMEXTS:=s S +CXXEXTS:=cpp c++ cc + +# probably shouldn't modify these, but you may need them below +ROOT=. +FWDIR:=$(ROOT)/firmware +BINDIR=$(ROOT)/bin +SRCDIR=$(ROOT)/src +INCDIR=$(ROOT)/include + +WARNFLAGS+= +EXTRA_CFLAGS= +EXTRA_CXXFLAGS= + +# Set to 1 to enable hot/cold linking +USE_PACKAGE:=1 + +# Set this to 1 to add additional rules to compile your project as a PROS library template +IS_LIBRARY:=0 +# TODO: CHANGE THIS! +LIBNAME:=libbest +VERSION:=1.0.0 +# EXCLUDE_SRC_FROM_LIB= $(SRCDIR)/unpublishedfile.c +# this line excludes opcontrol.c and similar files +EXCLUDE_SRC_FROM_LIB+=$(foreach file, $(SRCDIR)/opcontrol $(SRCDIR)/initialize $(SRCDIR)/autonomous,$(foreach cext,$(CEXTS),$(file).$(cext)) $(foreach cxxext,$(CXXEXTS),$(file).$(cxxext))) + +# files that get distributed to every user (beyond your source archive) - add +# whatever files you want here. This line is configured to add all header files +# that are in the the include directory get exported +TEMPLATE_FILES=$(INCDIR)/**/*.h $(INCDIR)/**/*.hpp + +.DEFAULT_GOAL=quick + +################################################################################ +################################################################################ +########## Nothing below this line should be edited by typical users ########### +-include ./common.mk diff --git a/bin/_pros_ld_timestamp.o b/bin/_pros_ld_timestamp.o new file mode 100644 index 0000000..c926318 Binary files /dev/null and b/bin/_pros_ld_timestamp.o differ diff --git a/bin/autonomous.cpp.o b/bin/autonomous.cpp.o new file mode 100644 index 0000000..309c937 Binary files /dev/null and b/bin/autonomous.cpp.o differ diff --git a/bin/initialize.cpp.o b/bin/initialize.cpp.o new file mode 100644 index 0000000..44adf41 Binary files /dev/null and b/bin/initialize.cpp.o differ diff --git a/bin/monolith.bin b/bin/monolith.bin new file mode 100644 index 0000000..ece44d7 Binary files /dev/null and b/bin/monolith.bin differ diff --git a/bin/monolith.elf b/bin/monolith.elf new file mode 100644 index 0000000..ac2f13d Binary files /dev/null and b/bin/monolith.elf differ diff --git a/bin/opcontrol.cpp.o b/bin/opcontrol.cpp.o new file mode 100644 index 0000000..c3d1288 Binary files /dev/null and b/bin/opcontrol.cpp.o differ diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..808a997 --- /dev/null +++ b/common.mk @@ -0,0 +1,256 @@ +ARCHTUPLE=arm-none-eabi- +DEVICE=VEX EDR V5 + +MFLAGS=-mcpu=cortex-a9 -mfpu=neon-fp16 -mfloat-abi=softfp +CPPFLAGS=-D_POSIX_THREADS -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -Os +GCCFLAGS=-ffunction-sections -fdata-sections -fdiagnostics-color + +WARNFLAGS+= + +SPACE := +SPACE += +COMMA := , + +LIBRARIES+=$(wildcard $(FWDIR)/*.a) +wlprefix=-Wl,$(subst $(SPACE),$(COMMA),$1) +LNK_FLAGS=--gc-sections --start-group $(strip $(LIBRARIES)) -lc -lm -lgcc -lstdc++ -lsupc++ --end-group + +ASMFLAGS=$(MFLAGS) $(WARNFLAGS) +CFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=gnu11 +CXXFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) -funwind-tables $(GCCFLAGS) --std=gnu++17 +LDFLAGS=$(MFLAGS) $(WARNFLAGS) -nostdlib +SIZEFLAGS=-d --common +NUMFMTFLAGS=--to=iec --format %.2f --suffix=B + +AR:=$(ARCHTUPLE)ar +# using arm-none-eabi-as generates a listing by default. This produces a super verbose output. +# Using gcc accomplishes the same thing without the extra output +AS:=$(ARCHTUPLE)gcc +CC:=$(ARCHTUPLE)gcc +CXX:=$(ARCHTUPLE)g++ +LD:=$(ARCHTUPLE)g++ +OBJCOPY:=$(ARCHTUPLE)objcopy +SIZETOOL:=$(ARCHTUPLE)size +READELF:=$(ARCHTUPLE)readelf +STRIP:=$(ARCHTUPLE)strip + +ifneq (, $(shell command -v gnumfmt 2> /dev/null)) + SIZES_NUMFMT:=| gnumfmt --field=-4 --header $(NUMFMTFLAGS) +else +ifneq (, $(shell command -v numfmt 2> /dev/null)) + SIZES_NUMFMT:=| numfmt --field=-4 --header $(NUMFMTFLAGS) +else + SIZES_NUMFMT:= +endif +endif + +ifneq (, $(shell command -v sed 2> /dev/null)) +SIZES_SED:=| sed -e 's/ dec/total/' +else +SIZES_SED:= +endif + +rwildcard=$(foreach d,$(filter-out $3,$(wildcard $1*)),$(call rwildcard,$d/,$2,$3)$(filter $(subst *,%,$2),$d)) + +# Colors +NO_COLOR=\x1b[0m +OK_COLOR=\x1b[32;01m +ERROR_COLOR=\x1b[31;01m +WARN_COLOR=\x1b[33;01m +STEP_COLOR=\x1b[37;01m +OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR) +DONE_STRING=$(OK_COLOR)[DONE]$(NO_COLOR) +ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR) +WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR) +ECHO=/bin/echo -e +echo=@$(ECHO) "$2$1$(NO_COLOR)" +echon=@$(ECHO) -n "$2$1$(NO_COLOR)" + +define test_output +@rm -f temp.log temp.errors +$1 2> temp.log || touch temp.errors +@if test -e temp.errors; then $(ECHO) "$(ERROR_STRING)" && cat temp.log; elif test -s temp.log; then $(ECHO) "$(WARN_STRING)" && cat temp.log; else $(ECHO) "$2"; fi; +@if test -e temp.errors; then rm -f temp.log temp.errors && false; fi; +@rm -f temp.log temp.errors +endef + +# Makefile Verbosity +ifeq ("$(origin VERBOSE)", "command line") +BUILD_VERBOSE = $(VERBOSE) +endif +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE = $(V) +endif + +ifndef BUILD_VERBOSE +BUILD_VERBOSE = 0 +endif + +# R is reduced (default messages) - build verbose = 0 +# V is verbose messages - verbosity = 1 +# VV is super verbose - verbosity = 2 +ifeq ($(BUILD_VERBOSE), 0) +R = @echo +D = @ +VV = @ +endif +ifeq ($(BUILD_VERBOSE), 1) +R = @echo +D = +VV = @ +endif +ifeq ($(BUILD_VERBOSE), 2) +R = +D = +VV = +endif + +INCLUDE=$(foreach dir,$(INCDIR) $(EXTRA_INCDIR),-iquote"$(dir)") + +ASMSRC=$(foreach asmext,$(ASMEXTS),$(call rwildcard, $(SRCDIR),*.$(asmext), $1)) +ASMOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call ASMSRC,$1))) +CSRC=$(foreach cext,$(CEXTS),$(call rwildcard, $(SRCDIR),*.$(cext), $1)) +COBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CSRC, $1))) +CXXSRC=$(foreach cxxext,$(CXXEXTS),$(call rwildcard, $(SRCDIR),*.$(cxxext), $1)) +CXXOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CXXSRC,$1))) + +GETALLOBJ=$(sort $(call ASMOBJ,$1) $(call COBJ,$1) $(call CXXOBJ,$1)) + +ARCHIVE_TEXT_LIST=$(subst $(SPACE),$(COMMA),$(notdir $(basename $(LIBRARIES)))) + +LDTIMEOBJ:=$(BINDIR)/_pros_ld_timestamp.o + +MONOLITH_BIN:=$(BINDIR)/monolith.bin +MONOLITH_ELF:=$(basename $(MONOLITH_BIN)).elf + +HOT_BIN:=$(BINDIR)/hot.package.bin +HOT_ELF:=$(basename $(HOT_BIN)).elf +COLD_BIN:=$(BINDIR)/cold.package.bin +COLD_ELF:=$(basename $(COLD_BIN)).elf + +# Check if USE_PACKAGE is defined to check for migration steps from purduesigbots/pros#87 +ifndef USE_PACKAGE +$(error Your Makefile must be migrated! Visit https://pros.cs.purdue.edu/v5/releases/kernel3.1.6.html to learn how) +endif + +DEFAULT_BIN=$(MONOLITH_BIN) +ifeq ($(USE_PACKAGE),1) +DEFAULT_BIN=$(HOT_BIN) +endif + +.PHONY: all clean quick + +quick: $(DEFAULT_BIN) + +all: clean $(DEFAULT_BIN) + +clean: + @echo Cleaning project + -$Drm -rf $(BINDIR) + +ifeq ($(IS_LIBRARY),1) +ifeq ($(LIBNAME),libbest) +$(errror "You should rename your library! libbest is the default library name and should be changed") +endif + +LIBAR=$(BINDIR)/$(LIBNAME).a +TEMPLATE_DIR=$(ROOT)/template + +clean-template: + @echo Cleaning $(TEMPLATE_DIR) + -$Drm -rf $(TEMPLATE_DIR) + +$(LIBAR): $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)) $(EXTRA_LIB_DEPS) + -$Drm -f $@ + @echo -n "Creating $@ " + $(call test_output,$D$(AR) rcs $@ $^, $(DONE_STRING)) + +.PHONY: library +library: $(LIBAR) + +.PHONY: template +template: clean-template $(LIBAR) + $Dprosv5 c create-template . $(LIBNAME) $(VERSION) $(foreach file,$(TEMPLATE_FILES) $(LIBAR),--system "$(file)") --target v5 $(CREATE_TEMPLATE_FLAGS) +endif + +# if project is a library source, compile the archive and link output.elf against the archive rather than source objects +ifeq ($(IS_LIBRARY),1) +ELF_DEPS=$(filter-out $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)), $(call GETALLOBJ,$(EXCLUDE_SRCDIRS))) +LIBRARIES+=$(LIBAR) +else +ELF_DEPS=$(call GETALLOBJ,$(EXCLUDE_SRCDIRS)) +endif + +$(MONOLITH_BIN): $(MONOLITH_ELF) $(BINDIR) + @echo -n "Creating $@ for $(DEVICE) " + $(call test_output,$D$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING)) + +$(MONOLITH_ELF): $(ELF_DEPS) $(LIBRARIES) + $(call _pros_ld_timestamp) + @echo -n "Linking project with $(ARCHIVE_TEXT_LIST) " + $(call test_output,$D$(LD) $(LDFLAGS) $(ELF_DEPS) $(LDTIMEOBJ) $(call wlprefix,-T$(FWDIR)/v5.ld $(LNK_FLAGS)) -o $@,$(OK_STRING)) + @echo Section sizes: + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) + +$(COLD_BIN): $(COLD_ELF) + @echo -n "Creating cold package binary for $(DEVICE) " + $(call test_output,$D$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING)) + +$(COLD_ELF): $(LIBRARIES) + $(call _pros_ld_timestamp) + @echo -n "Creating cold package with $(ARCHIVE_TEXT_LIST) " + $(call test_output,$D$(LD) $(LDFLAGS) $(LDTIMEOBJ) $(call wlprefix,--gc-keep-exported --whole-archive $^ -lstdc++ --no-whole-archive) $(call wlprefix,-T$(FWDIR)/v5.ld $(LNK_FLAGS) -o $@),$(OK_STRING)) + @echo -n "Stripping cold package " + $(call test_output,$D$(OBJCOPY) --strip-symbol=install_hot_table --strip-symbol=__libc_init_array --strip-symbol=_PROS_COMPILE_DIRECTORY --strip-symbol=_PROS_COMPILE_TIMESTAMP $@ $@, $(DONE_STRING)) + @echo Section sizes: + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) + +$(HOT_BIN): $(HOT_ELF) $(COLD_BIN) + @echo -n "Creating $@ for $(DEVICE) " + $(call test_output,$D$(OBJCOPY) $< -O binary $@,$(DONE_STRING)) + +$(HOT_ELF): $(COLD_ELF) $(ELF_DEPS) + $(call _pros_ld_timestamp) + @echo -n "Linking hot project with $(COLD_ELF) and $(ARCHIVE_TEXT_LIST) " + $(call test_output,$D$(LD) $(LDFLAGS) $(call wlprefix,-nostartfiles -R $<) $(filter-out $<,$^) $(LDTIMEOBJ) $(LIBRARIES) $(call wlprefix,-T$(FWDIR)/v5-hot.ld $(LNK_FLAGS) -o $@),$(OK_STRING)) + @echo Section sizes: + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) + +define asm_rule +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 + $(VV)mkdir -p $$(dir $$@) + @echo -n "Compiling $$< " + $$(call test_output,$D$(AS) -c $(ASMFLAGS) -o $$@ $$<,$(OK_STRING)) +endef +$(foreach asmext,$(ASMEXTS),$(eval $(call asm_rule,$(asmext)))) + +define c_rule +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 + $(VV)mkdir -p $$(dir $$@) + @echo -n "Compiling $$< " + $$(call test_output,$D$(CC) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CFLAGS) $(EXTRA_CFLAGS) -o $$@ $$<,$(OK_STRING)) +endef +$(foreach cext,$(CEXTS),$(eval $(call c_rule,$(cext)))) + +define cxx_rule +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 + $(VV)mkdir -p $$(dir $$@) + @echo -n "Compiling $$< " + $$(call test_output,$D$(CXX) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CXXFLAGS) $(EXTRA_CXXFLAGS) -o $$@ $$<,$(OK_STRING)) +endef +$(foreach cxxext,$(CXXEXTS),$(eval $(call cxx_rule,$(cxxext)))) + +define _pros_ld_timestamp +$(VV)mkdir -p $(dir $(LDTIMEOBJ)) +@echo -n "Adding timestamp " +@# Pipe a line of code defining _PROS_COMPILE_TOOLSTAMP and _PROS_COMPILE_DIRECTORY into GCC, +@# which allows compilation from stdin. We define _PROS_COMPILE_DIRECTORY using a command line-defined macro +@# which is the pwd | tail bit, which will truncate the path to the last 23 characters +$(call test_output, $(VV)echo 'char const * const _PROS_COMPILE_TIMESTAMP = __DATE__ " " __TIME__; char const * const _PROS_COMPILE_DIRECTORY = "$(shell pwd | tail -c 23)";' | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) -o $(LDTIMEOBJ) -,$(OK_STRING)) +endef + +# these rules are for build-compile-commands, which just print out sysroot information +cc-sysroot: + @echo | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) --verbose -o /dev/null - +cxx-sysroot: + @echo | $(CXX) -c -x c++ $(CXXFLAGS) $(EXTRA_CXXFLAGS) --verbose -o /dev/null - diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..525f8cd --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,107 @@ +[ + { + "arguments": [ + "clang++", + "-c", + "-target", + "armv7ar-none-none-eabi", + "-fno-ms-extensions", + "-fno-ms-compatibility", + "-fno-delayed-template-parsing", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/arm-none-eabi/thumb/v7-ar/fpv3/softfp", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/backward", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include-fixed", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include", + "-iquote./include", + "-iquote./include/./", + "-mcpu=cortex-a9", + "-mfpu=neon-fp16", + "-mfloat-abi=softfp", + "-D_POSIX_THREADS", + "-D_UNIX98_THREAD_MUTEX_ATTRIBUTES", + "-Os", + "-funwind-tables", + "-ffunction-sections", + "-fdata-sections", + "-fdiagnostics-color", + "--std=gnu++17", + "-o", + "bin/opcontrol.cpp.o", + "src\\opcontrol.cpp" + ], + "directory": "C:\\Users\\lerker100\\Documents\\Empty Pros Project", + "file": "src\\opcontrol.cpp" + }, + { + "arguments": [ + "clang++", + "-c", + "-target", + "armv7ar-none-none-eabi", + "-fno-ms-extensions", + "-fno-ms-compatibility", + "-fno-delayed-template-parsing", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/arm-none-eabi/thumb/v7-ar/fpv3/softfp", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/backward", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include-fixed", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include", + "-iquote./include", + "-iquote./include/./", + "-mcpu=cortex-a9", + "-mfpu=neon-fp16", + "-mfloat-abi=softfp", + "-D_POSIX_THREADS", + "-D_UNIX98_THREAD_MUTEX_ATTRIBUTES", + "-Os", + "-funwind-tables", + "-ffunction-sections", + "-fdata-sections", + "-fdiagnostics-color", + "--std=gnu++17", + "-o", + "bin/initialize.cpp.o", + "src\\initialize.cpp" + ], + "directory": "C:\\Users\\lerker100\\Documents\\Empty Pros Project", + "file": "src\\initialize.cpp" + }, + { + "arguments": [ + "clang++", + "-c", + "-target", + "armv7ar-none-none-eabi", + "-fno-ms-extensions", + "-fno-ms-compatibility", + "-fno-delayed-template-parsing", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/arm-none-eabi/thumb/v7-ar/fpv3/softfp", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include/c++/7.2.1/backward", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/include-fixed", + "-isystemc:\\program files\\pros\\toolchain\\usr\\bin\\../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/include", + "-iquote./include", + "-iquote./include/./", + "-mcpu=cortex-a9", + "-mfpu=neon-fp16", + "-mfloat-abi=softfp", + "-D_POSIX_THREADS", + "-D_UNIX98_THREAD_MUTEX_ATTRIBUTES", + "-Os", + "-funwind-tables", + "-ffunction-sections", + "-fdata-sections", + "-fdiagnostics-color", + "--std=gnu++17", + "-o", + "bin/autonomous.cpp.o", + "src\\autonomous.cpp" + ], + "directory": "C:\\Users\\lerker100\\Documents\\Empty Pros Project", + "file": "src\\autonomous.cpp" + } +] \ No newline at end of file diff --git a/firmware/libpros.a b/firmware/libpros.a new file mode 100644 index 0000000..0ebc943 Binary files /dev/null and b/firmware/libpros.a differ diff --git a/firmware/okapilib.a b/firmware/okapilib.a new file mode 100644 index 0000000..b6af6b5 Binary files /dev/null and b/firmware/okapilib.a differ diff --git a/firmware/v5-common.ld b/firmware/v5-common.ld new file mode 100644 index 0000000..dafa8d8 --- /dev/null +++ b/firmware/v5-common.ld @@ -0,0 +1,9 @@ +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x02E00000; /* ~48 MB */ + +MEMORY +{ + /* user code 72M */ + COLD_MEMORY : ORIGIN = 0x03800000, LENGTH = 0x04800000 /* Just under 19 MB */ + HEAP : ORIGIN = 0x04A00000, LENGTH = _HEAP_SIZE + HOT_MEMORY : ORIGIN = 0x07800000, LENGTH = 0x00800000 /* Just over 8 MB */ +} diff --git a/firmware/v5-hot.ld b/firmware/v5-hot.ld new file mode 100644 index 0000000..75594ef --- /dev/null +++ b/firmware/v5-hot.ld @@ -0,0 +1,236 @@ +/*******************************************************************/ +/* */ +/* This file is nearly the same as v5.ld, except that everything */ +/* goes in HOT_MEMORY and HOT user code doesn't need heap or stack */ +/* (only the cold memory code - PROS does) */ +/* */ +/*******************************************************************/ + +/* Define Memories in the system */ +INCLUDE firmware/v5-common.ld + +/* Make install_hot_table entry point so that linker can prune from there */ +ENTRY(install_hot_table) + +/* Define the sections, and where they are mapped in memory */ +SECTIONS +{ +/* Since install_hot_table is the entry point, it should be the first address + * in memory, but this makes sure it happens explicitly and consistently with + * cold linkage */ +.hot_init : { + KEEP (*(.hot_magic)) + KEEP (*(.hot_init)) +} > HOT_MEMORY +.text : { + KEEP (*(.vectors)) + /* boot data should be exactly 32 bytes long */ + *(.boot_data) + . = 0x20; + *(.boot) + . = ALIGN(64); + *(.freertos_vectors) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > HOT_MEMORY + +.init : { + KEEP (*(.init)) +} > HOT_MEMORY + +.fini : { + KEEP (*(.fini)) +} > HOT_MEMORY + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > HOT_MEMORY + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > HOT_MEMORY + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > HOT_MEMORY + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > HOT_MEMORY + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > HOT_MEMORY + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > HOT_MEMORY + +.got : { + *(.got) +} > HOT_MEMORY + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > HOT_MEMORY + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > HOT_MEMORY + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > HOT_MEMORY + +.eh_frame : { + *(.eh_frame) +} > HOT_MEMORY + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > HOT_MEMORY + +.gcc_except_table : { + *(.gcc_except_table) +} > HOT_MEMORY + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > HOT_MEMORY + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > HOT_MEMORY + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > HOT_MEMORY + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > HOT_MEMORY + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > HOT_MEMORY + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > HOT_MEMORY + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > HOT_MEMORY + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > HOT_MEMORY + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > HOT_MEMORY + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > HOT_MEMORY + +.bss (NOLOAD) : { + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; +} > HOT_MEMORY + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* HOT memory doesn't need a stack or heap */ +_end = .; +} diff --git a/firmware/v5.ld b/firmware/v5.ld new file mode 100644 index 0000000..d82db22 --- /dev/null +++ b/firmware/v5.ld @@ -0,0 +1,296 @@ +/*******************************************************************/ +/* */ +/* V5 SDK linker script v1.00 */ +/* */ +/* PROS NOTE: This file was modified off of the ldscript in the */ +/* CORTEX_A9_ZC702 FreeRTOS demo */ +/* */ +/* Copyright (c) 2017 IFI, Inc. All rights reserved. */ +/* */ +/* Description : Cortex-A9 Linker Script */ +/* */ +/*******************************************************************/ + +/* This stack is used during initialization, but FreeRTOS tasks have their own + stack allocated in BSS or Heap (kernel tasks in FreeRTOS .bss heap; user tasks + in standard heap) */ +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000; + +_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; +_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +INCLUDE firmware/v5-common.ld + +/* Specify the default entry point to the program */ + +ENTRY(vexStartup) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +/* THis will get stripped out before uploading, but we need to place code + here so we can at least link to it (install_hot_table) */ +.hot_init : { + KEEP (*(.hot_magic)) + KEEP (*(.hot_init)) +} > HOT_MEMORY + +.text : { + KEEP (*(.vectors)) + /* boot data should be exactly 32 bytes long */ + *(.boot_data) + . = 0x20; + *(.boot) + . = ALIGN(64); + *(.freertos_vectors) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > COLD_MEMORY + +.init : { + KEEP (*(.init)) +} > COLD_MEMORY + +.fini : { + KEEP (*(.fini)) +} > COLD_MEMORY + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > COLD_MEMORY + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > COLD_MEMORY + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > COLD_MEMORY + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > COLD_MEMORY + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > COLD_MEMORY + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > COLD_MEMORY + +.got : { + *(.got) +} > COLD_MEMORY + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > COLD_MEMORY + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > COLD_MEMORY + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > COLD_MEMORY + +.eh_frame : { + *(.eh_frame) +} > COLD_MEMORY + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > COLD_MEMORY + +.gcc_except_table : { + *(.gcc_except_table) +} > COLD_MEMORY + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > COLD_MEMORY + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > COLD_MEMORY + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > COLD_MEMORY + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > COLD_MEMORY + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > COLD_MEMORY + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > COLD_MEMORY + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > COLD_MEMORY + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > COLD_MEMORY + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > COLD_MEMORY + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > COLD_MEMORY + +.bss (NOLOAD) : { + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; +} > COLD_MEMORY + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(16); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > HEAP + +.stack (NOLOAD) : { + . = ALIGN(16); + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(16); + _stack = .; + __stack = _stack; + . = ALIGN(16); + _irq_stack_end = .; + . += _IRQ_STACK_SIZE; + . = ALIGN(16); + __irq_stack = .; + _supervisor_stack_end = .; + . += _SUPERVISOR_STACK_SIZE; + . = ALIGN(16); + __supervisor_stack = .; + _abort_stack_end = .; + . += _ABORT_STACK_SIZE; + . = ALIGN(16); + __abort_stack = .; + _fiq_stack_end = .; + . += _FIQ_STACK_SIZE; + . = ALIGN(16); + __fiq_stack = .; + _undef_stack_end = .; + . += _UNDEF_STACK_SIZE; + . = ALIGN(16); + __undef_stack = .; +} > COLD_MEMORY + +_end = .; +} diff --git a/include/api.h b/include/api.h new file mode 100644 index 0000000..411cce4 --- /dev/null +++ b/include/api.h @@ -0,0 +1,67 @@ +/** + * \file api.h + * + * PROS API header provides high-level user functionality + * + * Contains declarations for use by typical VEX programmers using PROS. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_API_H_ +#define _PROS_API_H_ + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include +#include +#include +#else /* (not) __cplusplus */ +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* __cplusplus */ + +#define PROS_VERSION_MAJOR 3 +#define PROS_VERSION_MINOR 1 +#define PROS_VERSION_PATCH 6 +#define PROS_VERSION_STRING "3.1.6" + +#define PROS_ERR (INT32_MAX) +#define PROS_ERR_F (INFINITY) + +#include "pros/adi.h" +#include "pros/colors.h" +#include "pros/llemu.h" +#include "pros/misc.h" +#include "pros/motors.h" +#include "pros/rtos.h" +#include "pros/vision.h" + +#ifdef __cplusplus +#include "pros/adi.hpp" +#include "pros/llemu.hpp" +#include "pros/misc.hpp" +#include "pros/motors.hpp" +#include "pros/rtos.hpp" +#include "pros/vision.hpp" +#endif + +#endif // _PROS_API_H_ diff --git a/include/display/README.md b/include/display/README.md new file mode 100644 index 0000000..afdfdeb --- /dev/null +++ b/include/display/README.md @@ -0,0 +1,71 @@ +# Littlev Graphics Libraray + +![LittlevGL cover](http://www.gl.littlev.hu/home/main_cover_small.png) + +LittlevGL provides everything you need to create a Graphical User Interface (GUI) on embedded systems with easy-to-use graphical elements, beautiful visual effects and low memory footprint. + +Homepage: https://littlevgl.com + +### Table Of Content +* [Key features](#key-features) +* [Porting](#porting) +* [Project set-up](#project-set-up) +* [PC simulator](#pc-simulator) +* [Screenshots](#screenshots) +* [Contributing](#contributing) +* [Donate](#donate) + +## Key features +* Powerful building blocks buttons, charts, lists, sliders, images etc +* Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling +* Various input devices touch pad, mouse, keyboard, encoder, buttons etc +* Multi language support with UTF-8 decoding +* Fully customizable graphical elements +* Hardware independent to use with any microcontroller or display +* Scalable to operate with few memory (50 kB Flash, 10 kB RAM) +* OS, External memory and GPU supported but not required +* Single frame buffer operation even with advances graphical effects +* Written in C for maximal compatibility +* Simulator to develop on PC without embedded hardware +* Tutorials, examples, themes for rapid development +* Documentation and API references online + +## Porting +In the most sime case you need 4 things: +1. Call `lv_tick_inc(1)` in every millisecods in a Timer or Task +2. Register a function which can **copy a pixel array** to an area of the screen +3. Register a function which can **read an input device**. (E.g. touch pad) +4. Call `lv_task_handler()` periodically in every few milliseconds +For more information visit https://littlevgl.com/porting + +## Project set-up +1. **Clone** or [Download](https://littlevgl.com/download) the lvgl repository: `git clone https://github.com/littlevgl/lvgl.git` +2. **Create project** with your preferred IDE and add the *lvgl* folder +3. Copy **lvgl/lv_conf_templ.h** as **lv_conf.h** next to the *lvgl* folder +4. In the lv_conf.h delete the first `#if 0` and its `#endif`. Let the default configurations at first. +5. In your *main.c*: #include "lvgl/lvgl.h" +6. In your *main function*: + * lvgl_init(); + * tick, display and input device initialization (see above) +7. To **test** create a label: `lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);` +8. In the main *while(1)* call `lv_task_handler();` and make a few milliseconds delay (e.g. `my_delay_ms(5);`) +9. Compile the code and load it to your embedded hardware + +## PC Simulator +If you don't have got an embedded hardware you can test the graphics library in a PC simulator. The simulator uses [SDL2](https://www.libsdl.org/) to emulate a display on your monitor and a touch pad with your mouse. + +There is a pre-configured PC project for **Eclipse CDT** in this repository: https://github.com/littlevgl/pc_simulator + +## Screenshots +![TFT material](http://www.gl.littlev.hu/github_res/tft_material.png) +![TFT zen](http://www.gl.littlev.hu/github_res/tft_zen.png) +![TFT alien](http://www.gl.littlev.hu/github_res/tft_alien.png) +![TFT night](http://www.gl.littlev.hu/github_res/tft_night.png) + +## Contributing +See [CONTRIBUTING.md](https://github.com/littlevgl/lvgl/blob/master/docs/CONTRIBUTING.md) + +## Donate +If you are pleased with the graphics library, found it useful or be happy with the support you got, please help its further development: + +[![Donate](https://littlevgl.com/donate_dir/donate_btn.png)](https://littlevgl.com/donate) diff --git a/include/display/licence.txt b/include/display/licence.txt new file mode 100644 index 0000000..beaef1d --- /dev/null +++ b/include/display/licence.txt @@ -0,0 +1,8 @@ +MIT licence +Copyright (c) 2016 Gábor Kiss-Vámosi + +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. diff --git a/include/display/lv_conf.h b/include/display/lv_conf.h new file mode 100644 index 0000000..d419e31 --- /dev/null +++ b/include/display/lv_conf.h @@ -0,0 +1,289 @@ +/** + * @file lv_conf.h + * + */ + +#ifndef LV_CONF_H +#define LV_CONF_H + +/*---------------- + * Dynamic memory + *----------------*/ + +/* Memory size which will be used by the library + * to store the graphical objects and other data */ +#define LV_MEM_CUSTOM \ + 1 /*1: use custom malloc/free, 0: use the built-in \ + lv_mem_alloc/lv_mem_free*/ +#if LV_MEM_CUSTOM == 0 +#define LV_MEM_SIZE \ + (32U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ +#define LV_MEM_ATTR /*Complier prefix for big array declaration*/ +#define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/ +#else /*LV_MEM_CUSTOM*/ +#define LV_MEM_CUSTOM_INCLUDE \ + "kapi.h" /*Header for the dynamic memory function*/ +#define LV_MEM_CUSTOM_ALLOC kmalloc /*Wrapper to malloc*/ +#define LV_MEM_CUSTOM_FREE kfree /*Wrapper to free*/ +#endif /*LV_MEM_CUSTOM*/ + +/*=================== + Graphical settings + *===================*/ + +/* Horizontal and vertical resolution of the library.*/ +#define LV_HOR_RES (480) +#define LV_VER_RES (240) +#define LV_DPI 126 + +/* Size of VDB (Virtual Display Buffer: the internal graphics buffer). + * Required for buffered drawing, opacity and anti-aliasing + * VDB makes the double buffering, you don't need to deal with it! + * Typical size: ~1/10 screen */ +#define LV_VDB_SIZE \ + (LV_VER_RES * \ + LV_HOR_RES) /*Size of VDB in pixel count (1/10 screen size is good for \ + first)*/ +#define LV_VDB_ADR \ + 0 /*Place VDB to a specific address (e.g. in external RAM) (0: allocate \ + automatically into RAM)*/ + +/* Use two Virtual Display buffers (VDB) parallelize rendering and flushing + * (optional) + * The flushing should use DMA to write the frame buffer in the background*/ +#define LV_VDB_DOUBLE 0 /*1: Enable the use of 2 VDBs*/ +#define LV_VDB2_ADR \ + 0 /*Place VDB2 to a specific address (e.g. in external RAM) (0: allocate \ + automatically into RAM)*/ + +/* Enable anti-aliasing (lines, and radiuses will be smoothed) */ +#define LV_ANTIALIAS 1 /*1: Enable anti-aliasing*/ + +/*Screen refresh settings*/ +#define LV_REFR_PERIOD 40 /*Screen refresh period in milliseconds*/ +#define LV_INV_FIFO_SIZE 32 /*The average count of objects on a screen */ + +/*================= + Misc. setting + *=================*/ + +/*Input device settings*/ +#define LV_INDEV_READ_PERIOD 50 /*Input device read period in milliseconds*/ +#define LV_INDEV_POINT_MARKER \ + 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/ +#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */ +#define LV_INDEV_DRAG_THROW \ + 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */ +#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/ +#define LV_INDEV_LONG_PRESS_REP_TIME \ + 100 /*Repeated trigger period in long press [ms] */ + +/*Color settings*/ +#define LV_COLOR_DEPTH 24 /*Color depth: 1/8/16/24*/ +#define LV_COLOR_TRANSP \ + LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma \ + keying)*/ + +/*Text settings*/ +#define LV_TXT_UTF8 1 /*Enable UTF-8 coded Unicode character usage */ +#define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/ + +/*Graphics feature usage*/ +#define USE_LV_ANIMATION 1 /*1: Enable all animations*/ +#define USE_LV_SHADOW 1 /*1: Enable shadows*/ +#define USE_LV_GROUP 1 /*1: Enable object groups (for keyboards)*/ +#define USE_LV_GPU 0 /*1: Enable GPU interface*/ +#define USE_LV_REAL_DRAW \ + 1 /*1: Enable function which draw directly to the frame buffer instead of \ + VDB (required if LV_VDB_SIZE = 0)*/ +#define USE_LV_FILESYSTEM 1 /*1: Enable file system (required by images*/ + +/*Compiler attributes*/ +#define LV_ATTRIBUTE_TICK_INC /* Define a custom attribute to tick increment \ + function */ +#define LV_ATTRIBUTE_TASK_HANDLER + +/*================ + * THEME USAGE + *================*/ +#define USE_LV_THEME_TEMPL 0 /*Just for test*/ +#define USE_LV_THEME_DEFAULT \ + 0 /*Built mainly from the built-in styles. Consumes very few RAM*/ +#define USE_LV_THEME_ALIEN 1 /*Dark futuristic theme*/ +#define USE_LV_THEME_NIGHT 0 /*Dark elegant theme*/ +#define USE_LV_THEME_MONO 0 /*Mono color theme for monochrome displays*/ +#define USE_LV_THEME_MATERIAL \ + 0 /*Flat theme with bold colors and light shadows*/ +#define USE_LV_THEME_ZEN 0 /*Peaceful, mainly light theme */ + +/*================== + * FONT USAGE + *===================*/ + +/* More info about fonts: https://littlevgl.com/basics#fonts + * To enable a built-in font use 1,2,4 or 8 values + * which will determine the bit-per-pixel */ +#define LV_FONT_DEFAULT \ + &lv_font_dejavu_20 /*Always set a default font from the built-in fonts*/ + +#define USE_LV_FONT_DEJAVU_10 0 +#define USE_LV_FONT_DEJAVU_10_LATIN_SUP 0 +#define USE_LV_FONT_DEJAVU_10_CYRILLIC 0 +#define USE_LV_FONT_SYMBOL_10 0 + +#define USE_LV_FONT_DEJAVU_20 4 +#define USE_LV_FONT_DEJAVU_20_LATIN_SUP 4 +#define USE_LV_FONT_DEJAVU_20_CYRILLIC 4 +#define USE_LV_FONT_SYMBOL_20 4 + +#define USE_LV_FONT_DEJAVU_30 0 +#define USE_LV_FONT_DEJAVU_30_LATIN_SUP 0 +#define USE_LV_FONT_DEJAVU_30_CYRILLIC 0 +#define USE_LV_FONT_SYMBOL_30 0 + +#define USE_LV_FONT_DEJAVU_40 0 +#define USE_LV_FONT_DEJAVU_40_LATIN_SUP 0 +#define USE_LV_FONT_DEJAVU_40_CYRILLIC 0 +#define USE_LV_FONT_SYMBOL_40 0 + +/* PROS adds the mono variant of DejaVu sans */ +#define USE_PROS_FONT_DEJAVU_MONO_10 0 +#define USE_PROS_FONT_DEJAVU_MONO_10_LATIN_SUP 0 + +#define USE_PROS_FONT_DEJAVU_MONO_20 4 +#define USE_PROS_FONT_DEJAVU_MONO_LATIN_SUP_20 4 + +#define USE_PROS_FONT_DEJAVU_MONO_30 0 +#define USE_PROS_FONT_DEJAVU_MONO_30_LATIN_SUP 0 + +#define USE_PROS_FONT_DEJAVU_MONO_40 0 +#define USE_PROS_FONT_DEJAVU_MONO_40_LATIN_SUP 0 + +/*=================== + * LV_OBJ SETTINGS + *==================*/ +#define LV_OBJ_FREE_NUM_TYPE \ + uint32_t /*Type of free number attribute (comment out disable free number)*/ +#define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/ + +/*================== + * LV OBJ X USAGE + *================*/ +/* + * Documentation of the object types: https://littlevgl.com/object-types + */ + +/***************** + * Simple object + *****************/ + +/*Label (dependencies: -*/ +#define USE_LV_LABEL 1 +#if USE_LV_LABEL != 0 +#define LV_LABEL_SCROLL_SPEED \ + 25 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_SCROLL/ROLL' \ + mode*/ +#endif + +/*Image (dependencies: lv_label*/ +#define USE_LV_IMG 1 + +/*Line (dependencies: -*/ +#define USE_LV_LINE 1 + +/******************* + * Container objects + *******************/ + +/*Container (dependencies: -*/ +#define USE_LV_CONT 1 + +/*Page (dependencies: lv_cont)*/ +#define USE_LV_PAGE 1 + +/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ +#define USE_LV_WIN 1 + +/*Tab (dependencies: lv_page, lv_btnm)*/ +#define USE_LV_TABVIEW 1 +#if USE_LV_TABVIEW != 0 +#define LV_TABVIEW_ANIM_TIME \ + 300 /*Time of slide animation [ms] (0: no animation)*/ +#endif + +/************************* + * Data visualizer objects + *************************/ + +/*Bar (dependencies: -)*/ +#define USE_LV_BAR 1 + +/*Line meter (dependencies: *;)*/ +#define USE_LV_LMETER 1 + +/*Gauge (dependencies:bar, lmeter)*/ +#define USE_LV_GAUGE 1 + +/*Chart (dependencies: -)*/ +#define USE_LV_CHART 1 + +/*LED (dependencies: -)*/ +#define USE_LV_LED 1 + +/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ +#define USE_LV_MBOX 1 + +/*Text area (dependencies: lv_label, lv_page)*/ +#define USE_LV_TA 1 +#if USE_LV_TA != 0 +#define LV_TA_CURSOR_BLINK_TIME 400 /*ms*/ +#define LV_TA_PWD_SHOW_TIME 1500 /*ms*/ +#endif + +/************************* + * User input objects + *************************/ + +/*Button (dependencies: lv_cont*/ +#define USE_LV_BTN 1 + +/*Button matrix (dependencies: -)*/ +#define USE_LV_BTNM 1 + +/*Keyboard (dependencies: lv_btnm)*/ +#define USE_LV_KB 0 + +/*Check box (dependencies: lv_btn, lv_label)*/ +#define USE_LV_CB 1 + +/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons + * ))*/ +#define USE_LV_LIST 1 +#if USE_LV_LIST != 0 +#define LV_LIST_FOCUS_TIME \ + 100 /*Default animation time of focusing to a list element [ms] (0: no \ + animation) */ +#endif + +/*Drop down list (dependencies: lv_page, lv_label)*/ +#define USE_LV_DDLIST 1 +#if USE_LV_DDLIST != 0 +#define LV_DDLIST_ANIM_TIME \ + 200 /*Open and close default animation time [ms] (0: no animation)*/ +#endif + +/*Roller (dependencies: lv_ddlist)*/ +#define USE_LV_ROLLER 1 +#if USE_LV_ROLLER != 0 +#define LV_ROLLER_ANIM_TIME \ + 200 /*Focus animation time [ms] (0: no \ + animation)*/ +#endif + +/*Slider (dependencies: lv_bar)*/ +#define USE_LV_SLIDER 1 + +/*Switch (dependencies: lv_slider)*/ +#define USE_LV_SW 1 + +#endif /*LV_CONF_H*/ diff --git a/include/display/lv_core/lv_core.mk b/include/display/lv_core/lv_core.mk new file mode 100644 index 0000000..b3939b4 --- /dev/null +++ b/include/display/lv_core/lv_core.mk @@ -0,0 +1,11 @@ +CSRCS += lv_group.c +CSRCS += lv_indev.c +CSRCS += lv_obj.c +CSRCS += lv_refr.c +CSRCS += lv_style.c +CSRCS += lv_vdb.c + +DEPPATH += --dep-path lvgl/lv_core +VPATH += :lvgl/lv_core + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_core" diff --git a/include/display/lv_core/lv_group.h b/include/display/lv_core/lv_group.h new file mode 100644 index 0000000..828bcb4 --- /dev/null +++ b/include/display/lv_core/lv_group.h @@ -0,0 +1,167 @@ +/** + * @file lv_group.h + * + */ + +#ifndef LV_GROUP_H +#define LV_GROUP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#include "lv_obj.h" + +/********************* + * DEFINES + *********************/ +/*Predefined keys to control the focused object via lv_group_send(group, c)*/ +/*For compatibility in signal function define the keys regardless to LV_GROUP*/ +#define LV_GROUP_KEY_UP 17 /*0x11*/ +#define LV_GROUP_KEY_DOWN 18 /*0x12*/ +#define LV_GROUP_KEY_RIGHT 19 /*0x13*/ +#define LV_GROUP_KEY_LEFT 20 /*0x14*/ +#define LV_GROUP_KEY_ESC 27 /*0x1B*/ +#define LV_GROUP_KEY_ENTER 10 /*0x0A, '\n'*/ +#define LV_GROUP_KEY_NEXT 9 /*0x09, '\t'*/ +#define LV_GROUP_KEY_PREV 11 /*0x0B, '*/ + +#define LV_GROUP_KEY_ENTER_LONG \ + 14 /*0x0E, Sent by the library if ENTER is long pressed*/ + +#if USE_LV_GROUP != 0 +/********************** + * TYPEDEFS + **********************/ +struct _lv_group_t; + +typedef void (*lv_group_style_mod_func_t)(lv_style_t *); +typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); + +typedef struct _lv_group_t { + lv_ll_t obj_ll; /*Linked list to store the objects in the group */ + lv_obj_t **obj_focus; /*The object in focus*/ + lv_group_style_mod_func_t + style_mod; /*A function which modifies the style of the focused object*/ + lv_group_focus_cb_t + focus_cb; /*A function to call when a new object is focused (optional)*/ + lv_style_t style_tmp; /*Stores the modified style of the focused object */ + uint8_t frozen : 1; /*1: can't focus to new object*/ +} lv_group_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a new object group + * @return pointer to the new object group + */ +lv_group_t *lv_group_create(void); + +/** + * Add an object to a group + * @param group pointer to a group + * @param obj pointer to an object to add + */ +void lv_group_add_obj(lv_group_t *group, lv_obj_t *obj); + +/** + * Remove an object from its group + * @param obj pointer to an object to remove + */ +void lv_group_remove_obj(lv_obj_t *obj); + +/** + * Focus on an object (defocus the current) + * @param obj pointer to an object to focus on + */ +void lv_group_focus_obj(lv_obj_t *obj); + +/** + * Focus the next object in a group (defocus the current) + * @param group pointer to a group + */ +void lv_group_focus_next(lv_group_t *group); + +/** + * Focus the previous object in a group (defocus the current) + * @param group pointer to a group + */ +void lv_group_focus_prev(lv_group_t *group); + +/** + * Do not let to change the focus from the current object + * @param group pointer to a group + * @param en true: freeze, false: release freezing (normal mode) + */ +void lv_group_focus_freeze(lv_group_t *group, bool en); + +/** + * Send a control character to the focuses object of a group + * @param group pointer to a group + * @param c a character (use LV_GROUP_KEY_.. to navigate) + */ +void lv_group_send_data(lv_group_t *group, uint32_t c); + +/** + * Set a function for a group which will modify the object's style if it is in + * focus + * @param group pointer to a group + * @param style_mod_func the style modifier function pointer + */ +void lv_group_set_style_mod_cb(lv_group_t *group, + lv_group_style_mod_func_t style_mod_func); + +/** + * Set a function for a group which will be called when a new object is focused + * @param group pointer to a group + * @param focus_cb the call back function or NULL if unused + */ +void lv_group_set_focus_cb(lv_group_t *group, lv_group_focus_cb_t focus_cb); + +/** + * Modify a style with the set 'style_mod' function. The input style remains + * unchanged. + * @param group pointer to group + * @param style pointer to a style to modify + * @return a copy of the input style but modified with the 'style_mod' function + */ +lv_style_t *lv_group_mod_style(lv_group_t *group, const lv_style_t *style); + +/** + * Get the focused object or NULL if there isn't one + * @param group pointer to a group + * @return pointer to the focused object + */ +lv_obj_t *lv_group_get_focused(lv_group_t *group); + +/** + * Get a the style modifier function of a group + * @param group pointer to a group + * @return pointer to the style modifier function + */ +lv_group_style_mod_func_t lv_group_get_style_mod_cb(lv_group_t *group); + +/** + * Get the focus callback function of a group + * @param group pointer to a group + * @return the call back function or NULL if not set + */ +lv_group_focus_cb_t lv_group_get_focus_cb(lv_group_t *group); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_GROUP != 0*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_GROUP_H*/ diff --git a/include/display/lv_core/lv_indev.h b/include/display/lv_core/lv_indev.h new file mode 100644 index 0000000..7adeaf4 --- /dev/null +++ b/include/display/lv_core/lv_indev.h @@ -0,0 +1,135 @@ +/** + * @file lv_indev_proc.h + * + */ + +#ifndef LV_INDEV_H +#define LV_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_core/lv_group.h" +#include "display/lv_hal/lv_hal_indev.h" +#include "lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the display input device subsystem + */ +void lv_indev_init(void); + +/** + * Get the currently processed input device. Can be used in action functions + * too. + * @return pointer to the currently processed input device or NULL if no input + * device processing right now + */ +lv_indev_t *lv_indev_get_act(void); + +/** + * Reset one or all input devices + * @param indev pointer to an input device to reset or NULL to reset all of them + */ +void lv_indev_reset(lv_indev_t *indev); + +/** + * Reset the long press state of an input device + * @param indev_proc pointer to an input device + */ +void lv_indev_reset_lpr(lv_indev_t *indev); + +/** + * Enable input devices device by type + * @param type Input device type + * @param enable true: enable this type; false: disable this type + */ +void lv_indev_enable(lv_hal_indev_type_t type, bool enable); + +/** + * Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and + * LV_INPUT_TYPE_BUTTON) + * @param indev pointer to an input device + * @param cur_obj pointer to an object to be used as cursor + */ +void lv_indev_set_cursor(lv_indev_t *indev, lv_obj_t *cur_obj); + +#if USE_LV_GROUP +/** + * Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @param group point to a group + */ +void lv_indev_set_group(lv_indev_t *indev, lv_group_t *group); +#endif + +/** + * Set the an array of points for LV_INDEV_TYPE_BUTTON. + * These points will be assigned to the buttons to press a specific point on the + * screen + * @param indev pointer to an input device + * @param group point to a group + */ +void lv_indev_set_button_points(lv_indev_t *indev, lv_point_t *points); + +/** + * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the result + */ +void lv_indev_get_point(lv_indev_t *indev, lv_point_t *point); + +/** + * Check if there is dragging with an input device or not (for + * LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return true: drag is in progress + */ +bool lv_indev_is_dragging(lv_indev_t *indev); + +/** + * Get the vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the vector + */ +void lv_indev_get_vect(lv_indev_t *indev, lv_point_t *point); +/** + * Get elapsed time since last press + * @param indev pointer to an input device (NULL to get the overall smallest + * inactivity) + * @return Elapsed ticks (milliseconds) since last press + */ +uint32_t lv_indev_get_inactive_time(lv_indev_t *indev); + +/** + * Do nothing until the next release + * @param indev pointer to an input device + */ +void lv_indev_wait_release(lv_indev_t *indev); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_INDEV_H*/ diff --git a/include/display/lv_core/lv_obj.h b/include/display/lv_core/lv_obj.h new file mode 100644 index 0000000..08ddb58 --- /dev/null +++ b/include/display/lv_core/lv_obj.h @@ -0,0 +1,753 @@ +/** + * @file lv_obj.h + * + */ + +#ifndef LV_OBJ_H +#define LV_OBJ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#include "display/lv_misc/lv_area.h" +#include "display/lv_misc/lv_color.h" +#include "display/lv_misc/lv_ll.h" +#include "display/lv_misc/lv_mem.h" +#include "lv_style.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/*Error check of lv_conf.h*/ +#if LV_HOR_RES == 0 || LV_VER_RES == 0 +#error "LittlevGL: LV_HOR_RES and LV_VER_RES must be greater then 0" +#endif + +#if LV_ANTIALIAS > 1 +#error "LittlevGL: LV_ANTIALIAS can be only 0 or 1" +#endif + +#if LV_VDB_SIZE == 0 && LV_ANTIALIAS != 0 +#error "LittlevGL: If LV_VDB_SIZE == 0 the anti-aliasing must be disabled" +#endif + +#if LV_VDB_SIZE > 0 && LV_VDB_SIZE < LV_HOR_RES +#error \ + "LittlevGL: Small Virtual Display Buffer (lv_conf.h: LV_VDB_SIZE >= LV_HOR_RES)" +#endif + +#if LV_VDB_SIZE == 0 && USE_LV_REAL_DRAW == 0 +#error \ + "LittlevGL: If LV_VDB_SIZE = 0 Real drawing function are required (lv_conf.h: USE_LV_REAL_DRAW 1)" +#endif + +#define LV_ANIM_IN \ + 0x00 /*Animation to show an object. 'OR' it with lv_anim_builtin_t*/ +#define LV_ANIM_OUT \ + 0x80 /*Animation to hide an object. 'OR' it with lv_anim_builtin_t*/ +#define LV_ANIM_DIR_MASK 0x80 /*ANIM_IN/ANIM_OUT mask*/ + +#define LV_MAX_ANCESTOR_NUM 8 +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; + +typedef enum { + LV_DESIGN_DRAW_MAIN, + LV_DESIGN_DRAW_POST, + LV_DESIGN_COVER_CHK, +} lv_design_mode_t; + +typedef bool (*lv_design_func_t)(struct _lv_obj_t *obj, const lv_area_t *mask_p, + lv_design_mode_t mode); + +typedef enum { + LV_RES_INV = 0, /*Typically indicates that the object is deleted (become + invalid) in the action function*/ + LV_RES_OK, /*The object is valid (no deleted) after the action*/ +} lv_res_t; + +typedef enum { + /*General signals*/ + LV_SIGNAL_CLEANUP, + LV_SIGNAL_CHILD_CHG, + LV_SIGNAL_CORD_CHG, + LV_SIGNAL_STYLE_CHG, + LV_SIGNAL_REFR_EXT_SIZE, + LV_SIGNAL_GET_TYPE, + + /*Input device related*/ + LV_SIGNAL_PRESSED, + LV_SIGNAL_PRESSING, + LV_SIGNAL_PRESS_LOST, + LV_SIGNAL_RELEASED, + LV_SIGNAL_LONG_PRESS, + LV_SIGNAL_LONG_PRESS_REP, + LV_SIGNAL_DRAG_BEGIN, + LV_SIGNAL_DRAG_END, + + /*Group related*/ + LV_SIGNAL_FOCUS, + LV_SIGNAL_DEFOCUS, + LV_SIGNAL_CONTROLL, +} lv_signal_t; + +typedef lv_res_t (*lv_signal_func_t)(struct _lv_obj_t *obj, lv_signal_t sign, + void *param); + +typedef struct _lv_obj_t { + struct _lv_obj_t *par; /*Pointer to the parent object*/ + lv_ll_t child_ll; /*Linked list to store the children objects*/ + + lv_area_t coords; /*Coordinates of the object (x1, y1, x2, y2)*/ + + lv_signal_func_t signal_func; /*Object type specific signal function*/ + lv_design_func_t design_func; /*Object type specific design function*/ + + void *ext_attr; /*Object type specific extended data*/ + lv_style_t *style_p; /*Pointer to the object's style*/ + +#if LV_OBJ_FREE_PTR != 0 + void *free_ptr; /*Application specific pointer (set it freely)*/ +#endif + +#if USE_LV_GROUP != 0 + void *group_p; /*Pointer to the group of the object*/ +#endif + /*Attributes and states*/ + uint8_t click : 1; /*1: Can be pressed by an input device*/ + uint8_t drag : 1; /*1: Enable the dragging*/ + uint8_t drag_throw : 1; /*1: Enable throwing with drag*/ + uint8_t drag_parent : 1; /*1: Parent will be dragged instead*/ + uint8_t hidden : 1; /*1: Object is hidden*/ + uint8_t top : 1; /*1: If the object or its children is clicked it goes to the + foreground*/ + uint8_t reserved : 1; + + uint8_t protect; /*Automatically happening actions can be prevented. 'OR'ed + values from lv_obj_prot_t*/ + + lv_coord_t + ext_size; /*EXTtend the size of the object in every direction. E.g. for + shadow drawing*/ + +#ifdef LV_OBJ_FREE_NUM_TYPE + LV_OBJ_FREE_NUM_TYPE + free_num; /*Application specific identifier (set it freely)*/ +#endif +} lv_obj_t; + +typedef lv_res_t (*lv_action_t)(struct _lv_obj_t *obj); + +/*Protect some attributes (max. 8 bit)*/ +typedef enum { + LV_PROTECT_NONE = 0x00, + LV_PROTECT_CHILD_CHG = + 0x01, /*Disable the child change signal. Used by the library*/ + LV_PROTECT_PARENT = + 0x02, /*Prevent automatic parent change (e.g. in lv_page)*/ + LV_PROTECT_POS = + 0x04, /*Prevent automatic positioning (e.g. in lv_cont layout)*/ + LV_PROTECT_FOLLOW = 0x08, /*Prevent the object be followed in automatic + ordering (e.g. in lv_cont PRETTY layout)*/ + LV_PROTECT_PRESS_LOST = 0x10, /*TODO */ +} lv_protect_t; + +/*Used by `lv_obj_get_type()`. The object's and its ancestor types are stored + * here*/ +typedef struct { + const char + *type[LV_MAX_ANCESTOR_NUM]; /*[0]: the actual type, [1]: ancestor, [2] + #1's ancestor ... [x]: "lv_obj" */ +} lv_obj_type_t; + +typedef enum { + LV_ALIGN_CENTER = 0, + LV_ALIGN_IN_TOP_LEFT, + LV_ALIGN_IN_TOP_MID, + LV_ALIGN_IN_TOP_RIGHT, + LV_ALIGN_IN_BOTTOM_LEFT, + LV_ALIGN_IN_BOTTOM_MID, + LV_ALIGN_IN_BOTTOM_RIGHT, + LV_ALIGN_IN_LEFT_MID, + LV_ALIGN_IN_RIGHT_MID, + LV_ALIGN_OUT_TOP_LEFT, + LV_ALIGN_OUT_TOP_MID, + LV_ALIGN_OUT_TOP_RIGHT, + LV_ALIGN_OUT_BOTTOM_LEFT, + LV_ALIGN_OUT_BOTTOM_MID, + LV_ALIGN_OUT_BOTTOM_RIGHT, + LV_ALIGN_OUT_LEFT_TOP, + LV_ALIGN_OUT_LEFT_MID, + LV_ALIGN_OUT_LEFT_BOTTOM, + LV_ALIGN_OUT_RIGHT_TOP, + LV_ALIGN_OUT_RIGHT_MID, + LV_ALIGN_OUT_RIGHT_BOTTOM, +} lv_align_t; + +typedef enum { + LV_ANIM_NONE = 0, + LV_ANIM_FLOAT_TOP, /*Float from/to the top*/ + LV_ANIM_FLOAT_LEFT, /*Float from/to the left*/ + LV_ANIM_FLOAT_BOTTOM, /*Float from/to the bottom*/ + LV_ANIM_FLOAT_RIGHT, /*Float from/to the right*/ + LV_ANIM_GROW_H, /*Grow/shrink horizontally*/ + LV_ANIM_GROW_V, /*Grow/shrink vertically*/ +} lv_anim_builtin_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init. the 'lv' library. + */ +void lv_init(void); + +/*-------------------- + * Create and delete + *-------------------*/ + +/** + * Create a basic object + * @param parent pointer to a parent object. + * If NULL then a screen will be created + * @param copy pointer to a base object, if not NULL then the new object will be + * copied from it + * @return pointer to the new object + */ +lv_obj_t *lv_obj_create(lv_obj_t *parent, lv_obj_t *copy); + +/** + * Delete 'obj' and all of its children + * @param obj pointer to an object to delete + * @return LV_RES_INV because the object is deleted + */ +lv_res_t lv_obj_del(lv_obj_t *obj); + +/** + * Delete all children of an object + * @param obj pointer to an object + */ +void lv_obj_clean(lv_obj_t *obj); + +/** + * Mark the object as invalid therefore its current position will be redrawn by + * 'lv_refr_task' + * @param obj pointer to an object + */ +void lv_obj_invalidate(lv_obj_t *obj); + +/*===================== + * Setter functions + *====================*/ + +/*-------------- + * Screen set + *--------------*/ + +/** + * Load a new screen + * @param scr pointer to a screen + */ +void lv_scr_load(lv_obj_t *scr); + +/*-------------------- + * Parent/children set + *--------------------*/ + +/** + * Set a new parent for an object. Its relative position will be the same. + * @param obj pointer to an object + * @param parent pointer to the new parent object + */ +void lv_obj_set_parent(lv_obj_t *obj, lv_obj_t *parent); + +/*-------------------- + * Coordinate set + * ------------------*/ + +/** + * Set relative the position of an object (relative to the parent) + * @param obj pointer to an object + * @param x new distance from the left side of the parent + * @param y new distance from the top of the parent + */ +void lv_obj_set_pos(lv_obj_t *obj, lv_coord_t x, lv_coord_t y); + +/** + * Set the x coordinate of a object + * @param obj pointer to an object + * @param x new distance from the left side from the parent + */ +void lv_obj_set_x(lv_obj_t *obj, lv_coord_t x); + +/** + * Set the y coordinate of a object + * @param obj pointer to an object + * @param y new distance from the top of the parent + */ +void lv_obj_set_y(lv_obj_t *obj, lv_coord_t y); + +/** + * Set the size of an object + * @param obj pointer to an object + * @param w new width + * @param h new height + */ +void lv_obj_set_size(lv_obj_t *obj, lv_coord_t w, lv_coord_t h); + +/** + * Set the width of an object + * @param obj pointer to an object + * @param w new width + */ +void lv_obj_set_width(lv_obj_t *obj, lv_coord_t w); + +/** + * Set the height of an object + * @param obj pointer to an object + * @param h new height + */ +void lv_obj_set_height(lv_obj_t *obj, lv_coord_t h); + +/** + * Align an object to an other object. + * @param obj pointer to an object to align + * @param base pointer to an object (if NULL the parent is used). 'obj' will be + * aligned to it. + * @param align type of alignment (see 'lv_align_t' enum) + * @param x_mod x coordinate shift after alignment + * @param y_mod y coordinate shift after alignment + */ +void lv_obj_align(lv_obj_t *obj, lv_obj_t *base, lv_align_t align, + lv_coord_t x_mod, lv_coord_t y_mod); + +/*--------------------- + * Appearance set + *--------------------*/ + +/** + * Set a new style for an object + * @param obj pointer to an object + * @param style_p pointer to the new style + */ +void lv_obj_set_style(lv_obj_t *obj, lv_style_t *style); + +/** + * Notify an object about its style is modified + * @param obj pointer to an object + */ +void lv_obj_refresh_style(lv_obj_t *obj); + +/** + * Notify all object if a style is modified + * @param style pointer to a style. Only the objects with this style will be + * notified + * (NULL to notify all objects) + */ +void lv_obj_report_style_mod(lv_style_t *style); + +/*----------------- + * Attribute set + *----------------*/ + +/** + * Hide an object. It won't be visible and clickable. + * @param obj pointer to an object + * @param en true: hide the object + */ +void lv_obj_set_hidden(lv_obj_t *obj, bool en); + +/** + * Enable or disable the clicking of an object + * @param obj pointer to an object + * @param en true: make the object clickable + */ +void lv_obj_set_click(lv_obj_t *obj, bool en); + +/** + * Enable to bring this object to the foreground if it + * or any of its children is clicked + * @param obj pointer to an object + * @param en true: enable the auto top feature + */ +void lv_obj_set_top(lv_obj_t *obj, bool en); + +/** + * Enable the dragging of an object + * @param obj pointer to an object + * @param en true: make the object dragable + */ +void lv_obj_set_drag(lv_obj_t *obj, bool en); + +/** + * Enable the throwing of an object after is is dragged + * @param obj pointer to an object + * @param en true: enable the drag throw + */ +void lv_obj_set_drag_throw(lv_obj_t *obj, bool en); + +/** + * Enable to use parent for drag related operations. + * If trying to drag the object the parent will be moved instead + * @param obj pointer to an object + * @param en true: enable the 'drag parent' for the object + */ +void lv_obj_set_drag_parent(lv_obj_t *obj, bool en); + +/** + * Set a bit or bits in the protect filed + * @param obj pointer to an object + * @param prot 'OR'-ed values from lv_obj_prot_t + */ +void lv_obj_set_protect(lv_obj_t *obj, uint8_t prot); + +/** + * Clear a bit or bits in the protect filed + * @param obj pointer to an object + * @param prot 'OR'-ed values from lv_obj_prot_t + */ +void lv_obj_clear_protect(lv_obj_t *obj, uint8_t prot); + +/** + * Set the signal function of an object. + * Always call the previous signal function in the new. + * @param obj pointer to an object + * @param fp the new signal function + */ +void lv_obj_set_signal_func(lv_obj_t *obj, lv_signal_func_t fp); + +/** + * Set a new design function for an object + * @param obj pointer to an object + * @param fp the new design function + */ +void lv_obj_set_design_func(lv_obj_t *obj, lv_design_func_t fp); + +/*---------------- + * Other set + *--------------*/ + +/** + * Allocate a new ext. data for an object + * @param obj pointer to an object + * @param ext_size the size of the new ext. data + * @return Normal pointer to the allocated ext + */ +void *lv_obj_allocate_ext_attr(lv_obj_t *obj, uint16_t ext_size); + +/** + * Send a 'LV_SIGNAL_REFR_EXT_SIZE' signal to the object + * @param obj pointer to an object + */ +void lv_obj_refresh_ext_size(lv_obj_t *obj); + +#ifdef LV_OBJ_FREE_NUM_TYPE +/** + * Set an application specific number for an object. + * It can help to identify objects in the application. + * @param obj pointer to an object + * @param free_num the new free number + */ +void lv_obj_set_free_num(lv_obj_t *obj, LV_OBJ_FREE_NUM_TYPE free_num); +#endif + +#if LV_OBJ_FREE_PTR != 0 +/** + * Set an application specific pointer for an object. + * It can help to identify objects in the application. + * @param obj pointer to an object + * @param free_p the new free pinter + */ +void lv_obj_set_free_ptr(lv_obj_t *obj, void *free_p); +#endif + +#if USE_LV_ANIMATION +/** + * Animate an object + * @param obj pointer to an object to animate + * @param type type of animation from 'lv_anim_builtin_t'. 'OR' it with ANIM_IN + * or ANIM_OUT + * @param time time of animation in milliseconds + * @param delay delay before the animation in milliseconds + * @param cb a function to call when the animation is ready + */ +void lv_obj_animate(lv_obj_t *obj, lv_anim_builtin_t type, uint16_t time, + uint16_t delay, void (*cb)(lv_obj_t *)); +#endif + +/*======================= + * Getter functions + *======================*/ + +/*------------------ + * Screen get + *-----------------*/ + +/** + * Return with a pointer to the active screen + * @return pointer to the active screen object (loaded by 'lv_scr_load()') + */ +lv_obj_t *lv_scr_act(void); + +/** + * Return with the top layer. (Same on every screen and it is above the normal + * screen layer) + * @return pointer to the top layer object (transparent screen sized lv_obj) + */ +lv_obj_t *lv_layer_top(void); + +/** + * Return with the system layer. (Same on every screen and it is above the all + * other layers) + * It is used for example by the cursor + * @return pointer to the system layer object (transparent screen sized lv_obj) + */ +lv_obj_t *lv_layer_sys(void); + +/** + * Return with the screen of an object + * @param obj pointer to an object + * @return pointer to a screen + */ +lv_obj_t *lv_obj_get_screen(lv_obj_t *obj); + +/*--------------------- + * Parent/children get + *--------------------*/ + +/** + * Returns with the parent of an object + * @param obj pointer to an object + * @return pointer to the parent of 'obj' + */ +lv_obj_t *lv_obj_get_parent(lv_obj_t *obj); + +/** + * Iterate through the children of an object (start from the "youngest, lastly + * created") + * @param obj pointer to an object + * @param child NULL at first call to get the next children + * and the previous return value later + * @return the child after 'act_child' or NULL if no more child + */ +lv_obj_t *lv_obj_get_child(lv_obj_t *obj, lv_obj_t *child); + +/** + * Iterate through the children of an object (start from the "oldest", firstly + * created) + * @param obj pointer to an object + * @param child NULL at first call to get the next children + * and the previous return value later + * @return the child after 'act_child' or NULL if no more child + */ +lv_obj_t *lv_obj_get_child_back(lv_obj_t *obj, lv_obj_t *child); + +/** + * Count the children of an object (only children directly on 'obj') + * @param obj pointer to an object + * @return children number of 'obj' + */ +uint16_t lv_obj_count_children(lv_obj_t *obj); + +/*--------------------- + * Coordinate get + *--------------------*/ + +/** + * Copy the coordinates of an object to an area + * @param obj pointer to an object + * @param cords_p pointer to an area to store the coordinates + */ +void lv_obj_get_coords(lv_obj_t *obj, lv_area_t *cords_p); + +/** + * Get the x coordinate of object + * @param obj pointer to an object + * @return distance of 'obj' from the left side of its parent + */ +lv_coord_t lv_obj_get_x(lv_obj_t *obj); + +/** + * Get the y coordinate of object + * @param obj pointer to an object + * @return distance of 'obj' from the top of its parent + */ +lv_coord_t lv_obj_get_y(lv_obj_t *obj); + +/** + * Get the width of an object + * @param obj pointer to an object + * @return the width + */ +lv_coord_t lv_obj_get_width(lv_obj_t *obj); + +/** + * Get the height of an object + * @param obj pointer to an object + * @return the height + */ +lv_coord_t lv_obj_get_height(lv_obj_t *obj); + +/** + * Get the extended size attribute of an object + * @param obj pointer to an object + * @return the extended size attribute + */ +lv_coord_t lv_obj_get_ext_size(lv_obj_t *obj); + +/*----------------- + * Appearance get + *---------------*/ + +/** + * Get the style pointer of an object (if NULL get style of the parent) + * @param obj pointer to an object + * @return pointer to a style + */ +lv_style_t *lv_obj_get_style(lv_obj_t *obj); + +/*----------------- + * Attribute get + *----------------*/ + +/** + * Get the hidden attribute of an object + * @param obj pointer to an object + * @return true: the object is hidden + */ +bool lv_obj_get_hidden(lv_obj_t *obj); + +/** + * Get the click enable attribute of an object + * @param obj pointer to an object + * @return true: the object is clickable + */ +bool lv_obj_get_click(lv_obj_t *obj); + +/** + * Get the top enable attribute of an object + * @param obj pointer to an object + * @return true: the auto top feture is enabled + */ +bool lv_obj_get_top(lv_obj_t *obj); + +/** + * Get the drag enable attribute of an object + * @param obj pointer to an object + * @return true: the object is dragable + */ +bool lv_obj_get_drag(lv_obj_t *obj); + +/** + * Get the drag thow enable attribute of an object + * @param obj pointer to an object + * @return true: drag throw is enabled + */ +bool lv_obj_get_drag_throw(lv_obj_t *obj); + +/** + * Get the drag parent attribute of an object + * @param obj pointer to an object + * @return true: drag parent is enabled + */ +bool lv_obj_get_drag_parent(lv_obj_t *obj); + +/** + * Get the protect field of an object + * @param obj pointer to an object + * @return protect field ('OR'ed values of lv_obj_prot_t) + */ +uint8_t lv_obj_get_protect(lv_obj_t *obj); + +/** + * Check at least one bit of a given protect bitfield is set + * @param obj pointer to an object + * @param prot protect bits to test ('OR'ed values of lv_obj_prot_t) + * @return false: none of the given bits are set, true: at least one bit is set + */ +bool lv_obj_is_protected(lv_obj_t *obj, uint8_t prot); + +/** + * Get the signal function of an object + * @param obj pointer to an object + * @return the signal function + */ +lv_signal_func_t lv_obj_get_signal_func(lv_obj_t *obj); + +/** + * Get the design function of an object + * @param obj pointer to an object + * @return the design function + */ +lv_design_func_t lv_obj_get_design_func(lv_obj_t *obj); + +/*------------------ + * Other get + *-----------------*/ + +/** + * Get the ext pointer + * @param obj pointer to an object + * @return the ext pointer but not the dynamic version + * Use it as ext->data1, and NOT da(ext)->data1 + */ +void *lv_obj_get_ext_attr(lv_obj_t *obj); + +/** + * Get object's and its ancestors type. Put their name in `type_buf` starting + * with the current type. + * E.g. buf.type[0]="lv_btn", buf.type[1]="lv_cont", buf.type[2]="lv_obj" + * @param obj pointer to an object which type should be get + * @param buf pointer to an `lv_obj_type_t` buffer to store the types + */ +void lv_obj_get_type(lv_obj_t *obj, lv_obj_type_t *buf); + +#ifdef LV_OBJ_FREE_NUM_TYPE +/** + * Get the free number + * @param obj pointer to an object + * @return the free number + */ +LV_OBJ_FREE_NUM_TYPE lv_obj_get_free_num(lv_obj_t *obj); +#endif + +#if LV_OBJ_FREE_PTR != 0 +/** + * Get the free pointer + * @param obj pointer to an object + * @return the free pointer + */ +void *lv_obj_get_free_ptr(lv_obj_t *obj); +#endif + +#if USE_LV_GROUP +/** + * Get the group of the object + * @param obj pointer to an object + * @return the pointer to group of the object + */ +void *lv_obj_get_group(lv_obj_t *obj); +#endif + +/********************** + * MACROS + **********************/ +#define LV_SCALE(x) (x << LV_ANTIALIAS) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_OBJ_H*/ diff --git a/include/display/lv_core/lv_refr.h b/include/display/lv_core/lv_refr.h new file mode 100644 index 0000000..0cd2a6d --- /dev/null +++ b/include/display/lv_core/lv_refr.h @@ -0,0 +1,88 @@ +/** + * @file lv_refr.h + * + */ + +#ifndef LV_REFR_H +#define LV_REFR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Initialize the screen refresh subsystem + */ +void lv_refr_init(void); + +/** + * Invalidate an area + * @param area_p pointer to area which should be invalidated + */ +void lv_inv_area(const lv_area_t *area_p); + +/** + * Set a function to call after every refresh to announce the refresh time and + * the number of refreshed pixels + * @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, + * uint32_t px_num)) + */ +void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t)); + +/** + * Called when an area is invalidated to modify the coordinates of the area. + * Special display controllers may require special coordinate rounding + * @param cb pointer to the a function which will modify the area + */ +void lv_refr_set_round_cb(void (*cb)(lv_area_t *)); + +/** + * Get the number of areas in the buffer + * @return number of invalid areas + */ +uint16_t lv_refr_get_buf_size(void); + +/** + * Pop (delete) the last 'num' invalidated areas from the buffer + * @param num number of areas to delete + */ +void lv_refr_pop_from_buf(uint16_t num); +/********************** + * STATIC FUNCTIONS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_REFR_H*/ diff --git a/include/display/lv_core/lv_style.h b/include/display/lv_core/lv_style.h new file mode 100644 index 0000000..c8c8886 --- /dev/null +++ b/include/display/lv_core/lv_style.h @@ -0,0 +1,181 @@ +/** + * @file lv_style.h + * + */ + +#ifndef LV_STYLE_H +#define LV_STYLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_misc/lv_anim.h" +#include "display/lv_misc/lv_area.h" +#include "display/lv_misc/lv_color.h" +#include "display/lv_misc/lv_font.h" +#include + +/********************* + * DEFINES + *********************/ +#define LV_RADIUS_CIRCLE \ + (LV_COORD_MAX) /*A very big radius to always draw as circle*/ + +/********************** + * TYPEDEFS + **********************/ + +/*Border types (Use 'OR'ed values)*/ +typedef enum { + LV_BORDER_NONE = 0x00, + LV_BORDER_BOTTOM = 0x01, + LV_BORDER_TOP = 0x02, + LV_BORDER_LEFT = 0x04, + LV_BORDER_RIGHT = 0x08, + LV_BORDER_FULL = 0x0F, +} lv_border_part_t; + +/*Shadow types*/ +typedef enum { + LV_SHADOW_BOTTOM = 0, + LV_SHADOW_FULL, +} lv_shadow_type_t; + +typedef struct { + uint8_t glass : 1; /*1: Do not inherit this style*/ + + struct { + lv_color_t main_color; + lv_color_t grad_color; + lv_coord_t radius; + lv_opa_t opa; + + struct { + lv_color_t color; + lv_coord_t width; + lv_border_part_t part; + lv_opa_t opa; + } border; + + struct { + lv_color_t color; + lv_coord_t width; + uint8_t type; + } shadow; + + struct { + lv_coord_t ver; + lv_coord_t hor; + lv_coord_t inner; + } padding; + + uint8_t empty : 1; /*Transparent background (border still drawn)*/ + } body; + + struct { + lv_color_t color; + const lv_font_t *font; + lv_coord_t letter_space; + lv_coord_t line_space; + lv_opa_t opa; + } text; + + struct { + lv_color_t color; + lv_opa_t intense; + lv_opa_t opa; + } image; + + struct { + lv_color_t color; + lv_coord_t width; + lv_opa_t opa; + } line; +} lv_style_t; + +#if USE_LV_ANIMATION +typedef struct { + const lv_style_t *style_start; /*Pointer to the starting style*/ + const lv_style_t *style_end; /*Pointer to the destination style*/ + lv_style_t *style_anim; /*Pointer to a style to animate*/ + lv_anim_cb_t end_cb; /*Call it when the animation is ready (NULL if unused)*/ + int16_t time; /*Animation time in ms*/ + int16_t + act_time; /*Current time in animation. Set to negative to make delay.*/ + uint16_t playback_pause; /*Wait before play back*/ + uint16_t repeat_pause; /*Wait before repeat*/ + uint8_t playback : 1; /*When the animation is ready play it back*/ + uint8_t repeat : 1; /*Repeat the animation infinitely*/ +} lv_style_anim_t; + +/* Example initialization +lv_style_anim_t a; +a.style_anim = &style_to_anim; +a.style_start = &style_1; +a.style_end = &style_2; +a.act_time = 0; +a.time = 1000; +a.playback = 0; +a.playback_pause = 0; +a.repeat = 0; +a.repeat_pause = 0; +a.end_cb = NULL; +lv_style_anim_create(&a); + */ +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init the basic styles + */ +void lv_style_init(void); + +/** + * Copy a style to an other + * @param dest pointer to the destination style + * @param src pointer to the source style + */ +void lv_style_copy(lv_style_t *dest, const lv_style_t *src); + +#if USE_LV_ANIMATION +/** + * Create an animation from a pre-configured 'lv_style_anim_t' variable + * @param anim pointer to a pre-configured 'lv_style_anim_t' variable (will be + * copied) + */ +void lv_style_anim_create(lv_style_anim_t *anim); +#endif + +/************************* + * GLOBAL VARIABLES + *************************/ +extern lv_style_t lv_style_scr; +extern lv_style_t lv_style_transp; +extern lv_style_t lv_style_transp_fit; +extern lv_style_t lv_style_transp_tight; +extern lv_style_t lv_style_plain; +extern lv_style_t lv_style_plain_color; +extern lv_style_t lv_style_pretty; +extern lv_style_t lv_style_pretty_color; +extern lv_style_t lv_style_btn_rel; +extern lv_style_t lv_style_btn_pr; +extern lv_style_t lv_style_btn_tgl_rel; +extern lv_style_t lv_style_btn_tgl_pr; +extern lv_style_t lv_style_btn_ina; + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_STYLE_H*/ diff --git a/include/display/lv_core/lv_vdb.h b/include/display/lv_core/lv_vdb.h new file mode 100644 index 0000000..5ea9511 --- /dev/null +++ b/include/display/lv_core/lv_vdb.h @@ -0,0 +1,71 @@ +/** + * @file lv_vdb.h + * + */ + +#ifndef LV_VDB_H +#define LV_VDB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if LV_VDB_SIZE != 0 + +#include "display/lv_misc/lv_area.h" +#include "display/lv_misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_area_t area; + lv_color_t *buf; +} lv_vdb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode + * @return pointer to a 'vdb' variable + */ +lv_vdb_t *lv_vdb_get(void); + +/** + * Flush the content of the vdb + */ +void lv_vdb_flush(void); + +/** + * In 'LV_VDB_DOUBLE' mode has to be called when 'disp_map()' + * is ready with copying the map to a frame buffer. + */ +void lv_flush_ready(void); + +/********************** + * MACROS + **********************/ + +#else /*LV_VDB_SIZE != 0*/ + +/*Just for compatibility*/ +void lv_flush_ready(void); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_VDB_H*/ diff --git a/include/display/lv_draw/lv_draw.h b/include/display/lv_draw/lv_draw.h new file mode 100644 index 0000000..72326a4 --- /dev/null +++ b/include/display/lv_draw/lv_draw.h @@ -0,0 +1,143 @@ +/** + * @file lv_draw.h + * + */ + +#ifndef LV_DRAW_H +#define LV_DRAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_core/lv_style.h" +#include "display/lv_misc/lv_txt.h" + +/********************* + * DEFINES + *********************/ +/*If image pixels contains alpha we need to know how much byte is a pixel*/ +#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 2 +#elif LV_COLOR_DEPTH == 16 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 3 +#elif LV_COLOR_DEPTH == 24 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 4 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/* Image header it is compatible with + * the result image converter utility*/ +typedef struct { + union { + struct { + uint32_t chroma_keyed : 1; /*1: The image contains transparent pixels with + LV_COLOR_TRANSP color*/ + uint32_t + alpha_byte : 1; /*Every pixel is extended with a 8 bit alpha channel*/ + uint32_t format : 6; /*See: lv_img_px_format*/ + uint32_t w : 12; /*Width of the image map*/ + uint32_t h : 12; /*Height of the image map*/ + } header; + uint8_t src_type; + }; + + union { + const uint8_t *pixel_map; /*For internal images (c arrays) pointer to the + pixels array*/ + uint8_t first_pixel; /*For external images (binary) the first byte of the + pixels (just for convenient)*/ + }; +} lv_img_t; + +typedef enum { + LV_IMG_FORMAT_UNKOWN = 0, + LV_IMG_FORMAT_INTERNAL_RAW, /*'lv_img_t' variable compiled with the code*/ + LV_IMG_FORMAT_FILE_RAW_RGB332, /*8 bit*/ + LV_IMG_FORMAT_FILE_RAW_RGB565, /*16 bit*/ + LV_IMG_FORMAT_FILE_RAW_RGB888, /*24 bit (stored on 32 bit)*/ +} lv_img_format_t; + +typedef enum { + LV_IMG_SRC_VARIABLE, + LV_IMG_SRC_FILE, + LV_IMG_SRC_SYMBOL, + LV_IMG_SRC_UNKNOWN, +} lv_img_src_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Draw a rectangle + * @param cords_p the coordinates of the rectangle + * @param mask_p the rectangle will be drawn only in this mask + * @param style_p pointer to a style + */ +void lv_draw_rect(const lv_area_t *cords_p, const lv_area_t *mask_p, + const lv_style_t *style_p); + +/*Experimental use for 3D modeling*/ +#define USE_LV_TRIANGLE 0 +#if USE_LV_TRIANGLE != 0 +/** + * + * @param points pointer to an array with 3 points + * @param mask_p the triangle will be drawn only in this mask + * @param color color of the triangle + */ +void lv_draw_triangle(const lv_point_t *points, const lv_area_t *mask_p, + lv_color_t color); +#endif + +/** + * Write a text + * @param cords_p coordinates of the label + * @param mask_p the label will be drawn only in this area + * @param style_p pointer to a style + * @param txt 0 terminated text to write + * @param flags settings for the text from 'txt_flag_t' enum + * @param offset text offset in x and y direction (NULL if unused) + */ +void lv_draw_label(const lv_area_t *cords_p, const lv_area_t *mask_p, + const lv_style_t *style_p, const char *txt, + lv_txt_flag_t flag, lv_point_t *offset); + +#if USE_LV_IMG +/** + * Draw an image + * @param cords_p the coordinates of the image + * @param mask_p the image will be drawn only in this area + * @param map_p pointer to a lv_color_t array which contains the pixels of the + * image + */ +void lv_draw_img(const lv_area_t *coords, const lv_area_t *mask, + const lv_style_t *style, const void *src); +#endif + +/** + * Draw a line + * @param p1 first point of the line + * @param p2 second point of the line + * @param mask_pthe line will be drawn only on this area + * @param style_p pointer to a style + */ +void lv_draw_line(const lv_point_t *p1, const lv_point_t *p2, + const lv_area_t *mask_p, const lv_style_t *style_p); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_DRAW_H*/ diff --git a/include/display/lv_draw/lv_draw.mk b/include/display/lv_draw/lv_draw.mk new file mode 100644 index 0000000..5fcf2b0 --- /dev/null +++ b/include/display/lv_draw/lv_draw.mk @@ -0,0 +1,8 @@ +CSRCS += lv_draw_vbasic.c +CSRCS += lv_draw.c +CSRCS += lv_draw_rbasic.c + +DEPPATH += --dep-path lvgl/lv_draw +VPATH += :lvgl/lv_draw + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_draw" diff --git a/include/display/lv_draw/lv_draw_rbasic.h b/include/display/lv_draw/lv_draw_rbasic.h new file mode 100644 index 0000000..d85eb5b --- /dev/null +++ b/include/display/lv_draw/lv_draw_rbasic.h @@ -0,0 +1,95 @@ +/** + * @file lv_draw_rbasic..h + * + */ + +#ifndef LV_DRAW_RBASIC_H +#define LV_DRAW_RBASIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_REAL_DRAW != 0 + +#include "display/lv_misc/lv_area.h" +#include "display/lv_misc/lv_color.h" +#include "display/lv_misc/lv_font.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_rpx(lv_coord_t x, lv_coord_t y, const lv_area_t *mask_p, + lv_color_t color, lv_opa_t opa); + +/** + * Fill an area on the display + * @param cords_p coordinates of the area to fill + * @param mask_p fill only o this mask + * @param color fill color + * @param opa opacity (ignored, only for compatibility with lv_vfill) + */ +void lv_rfill(const lv_area_t *cords_p, const lv_area_t *mask_p, + lv_color_t color, lv_opa_t opa); + +/** + * Draw a letter to the display + * @param pos_p left-top coordinate of the latter + * @param mask_p the letter will be drawn only on this area + * @param font_p pointer to font + * @param letter a letter to draw + * @param color color of letter + * @param opa opacity of letter (ignored, only for compatibility with + * lv_vletter) + */ +void lv_rletter(const lv_point_t *pos_p, const lv_area_t *mask_p, + const lv_font_t *font_p, uint32_t letter, lv_color_t color, + lv_opa_t opa); + +/** + * When the letter is ant-aliased it needs to know the background color + * @param bg_color the background color of the currently drawn letter + */ +void lv_rletter_set_background(lv_color_t color); + +/** + * Draw a color map to the display (image) + * @param cords_p coordinates the color map + * @param mask_p the map will drawn only on this area + * @param map_p pointer to a lv_color_t array + * @param opa opacity of the map (ignored, only for compatibility with + * 'lv_vmap') + * @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color + * pixels + * @param alpha_byte true: extra alpha byte is inserted for every pixel (not + * supported, only l'v_vmap' can draw it) + * @param recolor mix the pixels with this color + * @param recolor_opa the intense of recoloring + */ +void lv_rmap(const lv_area_t *cords_p, const lv_area_t *mask_p, + const uint8_t *map_p, lv_opa_t opa, bool chroma_key, + bool alpha_byte, lv_color_t recolor, lv_opa_t recolor_opa); +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_REAL_DRAW*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_DRAW_RBASIC_H*/ diff --git a/include/display/lv_draw/lv_draw_vbasic.h b/include/display/lv_draw/lv_draw_vbasic.h new file mode 100644 index 0000000..8667647 --- /dev/null +++ b/include/display/lv_draw/lv_draw_vbasic.h @@ -0,0 +1,92 @@ +/** + * @file lv_draw_vbasic.h + * + */ + +#ifndef LV_DRAW_VBASIC_H +#define LV_DRAW_VBASIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if LV_VDB_SIZE != 0 + +#include "display/lv_misc/lv_area.h" +#include "display/lv_misc/lv_color.h" +#include "display/lv_misc/lv_font.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_vpx(lv_coord_t x, lv_coord_t y, const lv_area_t *mask_p, + lv_color_t color, lv_opa_t opa); +/** + * Fill an area in the Virtual Display Buffer + * @param cords_p coordinates of the area to fill + * @param mask_p fill only o this mask + * @param color fill color + * @param opa opacity of the area (0..255) + */ +void lv_vfill(const lv_area_t *cords_p, const lv_area_t *mask_p, + lv_color_t color, lv_opa_t opa); + +/** + * Draw a letter in the Virtual Display Buffer + * @param pos_p left-top coordinate of the latter + * @param mask_p the letter will be drawn only on this area + * @param font_p pointer to font + * @param letter a letter to draw + * @param color color of letter + * @param opa opacity of letter (0..255) + */ +void lv_vletter(const lv_point_t *pos_p, const lv_area_t *mask_p, + const lv_font_t *font_p, uint32_t letter, lv_color_t color, + lv_opa_t opa); + +/** + * Draw a color map to the display (image) + * @param cords_p coordinates the color map + * @param mask_p the map will drawn only on this area (truncated to VDB area) + * @param map_p pointer to a lv_color_t array + * @param opa opacity of the map + * @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color + * pixels + * @param alpha_byte true: extra alpha byte is inserted for every pixel + * @param recolor mix the pixels with this color + * @param recolor_opa the intense of recoloring + */ +void lv_vmap(const lv_area_t *cords_p, const lv_area_t *mask_p, + const uint8_t *map_p, lv_opa_t opa, bool chroma_key, + bool alpha_byte, lv_color_t recolor, lv_opa_t recolor_opa); + +/** + * Reallocate 'color_map_tmp' to the new hor. res. size. It is used in 'sw_fill' + */ +void lv_vdraw_refresh_temp_arrays(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_VDB_SIZE != 0*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_DRAW_RBASIC_H*/ diff --git a/include/display/lv_hal/lv_hal.h b/include/display/lv_hal/lv_hal.h new file mode 100644 index 0000000..5ab28f2 --- /dev/null +++ b/include/display/lv_hal/lv_hal.h @@ -0,0 +1,40 @@ +/** + * @file hal.h + * + */ + +#ifndef HAL_H +#define HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_hal_disp.h" +#include "lv_hal_indev.h" +#include "lv_hal_tick.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_hal/lv_hal.mk b/include/display/lv_hal/lv_hal.mk new file mode 100644 index 0000000..9074809 --- /dev/null +++ b/include/display/lv_hal/lv_hal.mk @@ -0,0 +1,8 @@ +CSRCS += lv_hal_disp.c +CSRCS += lv_hal_indev.c +CSRCS += lv_hal_tick.c + +DEPPATH += --dep-path lvgl/lv_hal +VPATH += :lvgl/lv_hal + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_hal" diff --git a/include/display/lv_hal/lv_hal_disp.h b/include/display/lv_hal/lv_hal_disp.h new file mode 100644 index 0000000..8d3529c --- /dev/null +++ b/include/display/lv_hal/lv_hal_disp.h @@ -0,0 +1,183 @@ +/** + * @file hal_disp.h + * + * @description Display Driver HAL interface header file + * + */ + +#ifndef HAL_DISP_H +#define HAL_DISP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_misc/lv_color.h" +#include "lv_hal.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Display Driver structure to be registered by HAL + */ +typedef struct _disp_drv_t { + /*Write the internal buffer (VDB) to the display. 'lv_flush_ready()' has to be + * called when finished*/ + void (*disp_flush)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t *color_p); + + /*Fill an area with a color on the display*/ + void (*disp_fill)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + lv_color_t color); + + /*Write pixel map (e.g. image) to the display*/ + void (*disp_map)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t *color_p); + +#if USE_LV_GPU + /*Blend two memories using opacity (GPU only)*/ + void (*mem_blend)(lv_color_t *dest, const lv_color_t *src, uint32_t length, + lv_opa_t opa); + + /*Fill a memory with a color (GPU only)*/ + void (*mem_fill)(lv_color_t *dest, uint32_t length, lv_color_t color); +#endif + +} lv_disp_drv_t; + +typedef struct _disp_t { + lv_disp_drv_t driver; + struct _disp_t *next; +} lv_disp_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize a display driver with default values. + * It is used to surly have known values in the fields ant not memory junk. + * After it you can set the fields. + * @param driver pointer to driver variable to initialize + */ +void lv_disp_drv_init(lv_disp_drv_t *driver); + +/** + * Register an initialized display driver. + * Automatically set the first display as active. + * @param driver pointer to an initialized 'lv_disp_drv_t' variable (can be + * local variable) + * @return pointer to the new display or NULL on error + */ +lv_disp_t *lv_disp_drv_register(lv_disp_drv_t *driver); + +/** + * Set the active display + * @param disp pointer to a display (return value of 'lv_disp_register') + */ +void lv_disp_set_active(lv_disp_t *disp); + +/** + * Get a pointer to the active display + * @return pointer to the active display + */ +lv_disp_t *lv_disp_get_active(void); + +/** + * Get the next display. + * @param disp pointer to the current display. NULL to initialize. + * @return the next display or NULL if no more. Give the first display when the + * parameter is NULL + */ +lv_disp_t *lv_disp_next(lv_disp_t *disp); + +/** + * Fill a rectangular area with a color on the active display + * @param x1 left coordinate of the rectangle + * @param x2 right coordinate of the rectangle + * @param y1 top coordinate of the rectangle + * @param y2 bottom coordinate of the rectangle + * @param color_p pointer to an array of colors + */ +void lv_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + lv_color_t *color_p); + +/** + * Fill a rectangular area with a color on the active display + * @param x1 left coordinate of the rectangle + * @param x2 right coordinate of the rectangle + * @param y1 top coordinate of the rectangle + * @param y2 bottom coordinate of the rectangle + * @param color fill color + */ +void lv_disp_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + lv_color_t color); + +/** + * Put a color map to a rectangular area on the active display + * @param x1 left coordinate of the rectangle + * @param x2 right coordinate of the rectangle + * @param y1 top coordinate of the rectangle + * @param y2 bottom coordinate of the rectangle + * @param color_map pointer to an array of colors + */ +void lv_disp_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, + const lv_color_t *color_map); + +#if USE_LV_GPU +/** + * Blend pixels to a destination memory from a source memory + * In 'lv_disp_drv_t' 'mem_blend' is optional. (NULL if not available) + * @param dest a memory address. Blend 'src' here. + * @param src pointer to pixel map. Blend it to 'dest'. + * @param length number of pixels in 'src' + * @param opa opacity (0, LV_OPA_TRANSP: transparent ... 255, LV_OPA_COVER, + * fully cover) + */ +void lv_disp_mem_blend(lv_color_t *dest, const lv_color_t *src, uint32_t length, + lv_opa_t opa); + +/** + * Fill a memory with a color (GPUs may support it) + * In 'lv_disp_drv_t' 'mem_fill' is optional. (NULL if not available) + * @param dest a memory address. Copy 'src' here. + * @param src pointer to pixel map. Copy it to 'dest'. + * @param length number of pixels in 'src' + * @param opa opacity (0, LV_OPA_TRANSP: transparent ... 255, LV_OPA_COVER, + * fully cover) + */ +void lv_disp_mem_fill(lv_color_t *dest, uint32_t length, lv_color_t color); +/** + * Shows if memory blending (by GPU) is supported or not + * @return false: 'mem_blend' is not supported in the driver; true: 'mem_blend' + * is supported in the driver + */ +bool lv_disp_is_mem_blend_supported(void); + +/** + * Shows if memory fill (by GPU) is supported or not + * @return false: 'mem_fill' is not supported in the drover; true: 'mem_fill' is + * supported in the driver + */ +bool lv_disp_is_mem_fill_supported(void); +#endif +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_hal/lv_hal_indev.h b/include/display/lv_hal/lv_hal_indev.h new file mode 100644 index 0000000..a783fb6 --- /dev/null +++ b/include/display/lv_hal/lv_hal_indev.h @@ -0,0 +1,162 @@ +/** + * @file hal_indev.h + * + * @description Input Device HAL interface layer header file + * + */ + +#ifndef HAL_INDEV_H +#define HAL_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_misc/lv_area.h" +#include "lv_hal.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Possible input device types*/ +typedef enum { + LV_INDEV_TYPE_NONE, /*Show uninitialized state*/ + LV_INDEV_TYPE_POINTER, /*Touch pad, mouse, external button*/ + LV_INDEV_TYPE_KEYPAD, /*Keypad or keyboard*/ + LV_INDEV_TYPE_BUTTON, /*External (hardware button) which is assinged to a + specific point of the screen*/ +} lv_hal_indev_type_t; + +/*States for input devices*/ +typedef enum { LV_INDEV_STATE_REL = 0, LV_INDEV_STATE_PR } lv_indev_state_t; + +/*Data type when an input device is read */ +typedef struct { + union { + lv_point_t point; /*For LV_INDEV_TYPE_POINTER the currently pressed point*/ + uint32_t key; /*For LV_INDEV_TYPE_KEYPAD the currently pressed key*/ + uint32_t btn; /*For LV_INDEV_TYPE_BUTTON the currently pressed button*/ + }; + lv_indev_state_t state; /*LV_INDEV_EVENT_REL or LV_INDEV_EVENT_PR*/ + void *user_data; /*'lv_indev_drv_t.priv' for this driver*/ +} lv_indev_data_t; + +/*Initialized by the user and registered by 'lv_indev_add()'*/ +typedef struct { + lv_hal_indev_type_t type; /*Input device type*/ + bool (*read)(lv_indev_data_t *data); /*Function pointer to read data. Return + 'true' if there is still data to be + read (buffered)*/ + void *user_data; /*Pointer to user defined data, passed in 'lv_indev_data_t' + on read*/ +} lv_indev_drv_t; + +struct _lv_obj_t; + +/*Run time data of input devices*/ +typedef struct _lv_indev_proc_t { + lv_indev_state_t state; + union { + struct { /*Pointer and button data*/ + lv_point_t act_point; + lv_point_t last_point; + lv_point_t vect; + lv_point_t + drag_sum; /*Count the dragged pixels to check LV_INDEV_DRAG_LIMIT*/ + struct _lv_obj_t *act_obj; + struct _lv_obj_t *last_obj; + + /*Flags*/ + uint8_t drag_range_out : 1; + uint8_t drag_in_prog : 1; + uint8_t wait_unil_release : 1; + }; + struct { /*Keypad data*/ + lv_indev_state_t last_state; + uint32_t last_key; + }; + }; + + uint32_t pr_timestamp; /*Pressed time stamp*/ + uint32_t longpr_rep_timestamp; /*Long press repeat time stamp*/ + + /*Flags*/ + uint8_t long_pr_sent : 1; + uint8_t reset_query : 1; + uint8_t disabled : 1; +} lv_indev_proc_t; + +struct _lv_obj_t; +struct _lv_group_t; + +/*The main input device descriptor with driver, runtime data ('proc') and some + * additional information*/ +typedef struct _lv_indev_t { + lv_indev_drv_t driver; + lv_indev_proc_t proc; + uint32_t last_activity_time; + union { + struct _lv_obj_t *cursor; /*Cursor for LV_INPUT_TYPE_POINTER*/ + struct _lv_group_t *group; /*Keypad destination group*/ + lv_point_t + *btn_points; /*Array points assigned to the button ()screen will be + pressed here by the buttons*/ + }; + struct _lv_indev_t *next; +} lv_indev_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an input device driver with default values. + * It is used to surly have known values in the fields ant not memory junk. + * After it you can set the fields. + * @param driver pointer to driver variable to initialize + */ +void lv_indev_drv_init(lv_indev_drv_t *driver); + +/** + * Register an initialized input device driver. + * @param driver pointer to an initialized 'lv_indev_drv_t' variable (can be + * local variable) + * @return pointer to the new input device or NULL on error + */ +lv_indev_t *lv_indev_drv_register(lv_indev_drv_t *driver); + +/** + * Get the next input device. + * @param indev pointer to the current input device. NULL to initialize. + * @return the next input devise or NULL if no more. Gives the first input + * device when the parameter is NULL + */ +lv_indev_t *lv_indev_next(lv_indev_t *indev); + +/** + * Read data from an input device. + * @param indev pointer to an input device + * @param data input device will write its data here + * @return false: no more data; true: there more data to read (buffered) + */ +bool lv_indev_read(lv_indev_t *indev, lv_indev_data_t *data); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_hal/lv_hal_tick.h b/include/display/lv_hal/lv_hal_tick.h new file mode 100644 index 0000000..c7a28ef --- /dev/null +++ b/include/display/lv_hal/lv_hal_tick.h @@ -0,0 +1,61 @@ +/** + * @file lv_hal_tick.h + * Provide access to the system tick with 1 millisecond resolution + */ + +#ifndef LV_HAL_TICK_H +#define LV_HAL_TICK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ +#ifndef LV_ATTRIBUTE_TICK_INC +#define LV_ATTRIBUTE_TICK_INC +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * You have to call this function periodically + * @param tick_period the call period of this function in milliseconds + */ +LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period); + +/** + * Get the elapsed milliseconds since start up + * @return the elapsed milliseconds + */ +uint32_t lv_tick_get(void); + +/** + * Get the elapsed milliseconds science a previous time stamp + * @param prev_tick a previous time stamp (return value of systick_get() ) + * @return the elapsed milliseconds since 'prev_tick' + */ +uint32_t lv_tick_elaps(uint32_t prev_tick); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_HAL_TICK_H*/ diff --git a/include/display/lv_misc/lv_anim.h b/include/display/lv_misc/lv_anim.h new file mode 100644 index 0000000..69b8453 --- /dev/null +++ b/include/display/lv_misc/lv_anim.h @@ -0,0 +1,128 @@ +/** + * @file anim.h + * + */ + +#ifndef ANIM_H +#define ANIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_ANIMATION + +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_anim_t; + +typedef int32_t (*lv_anim_path_t)(const struct _lv_anim_t *); + +typedef void (*lv_anim_fp_t)(void *, int32_t); +typedef void (*lv_anim_cb_t)(void *); + +typedef struct _lv_anim_t { + void *var; /*Variable to animate*/ + lv_anim_fp_t fp; /*Animator function*/ + lv_anim_cb_t end_cb; /*Call it when the animation is ready*/ + lv_anim_path_t path; /*An array with the steps of animations*/ + int32_t start; /*Start value*/ + int32_t end; /*End value*/ + int16_t time; /*Animation time in ms*/ + int16_t + act_time; /*Current time in animation. Set to negative to make delay.*/ + uint16_t playback_pause; /*Wait before play back*/ + uint16_t repeat_pause; /*Wait before repeat*/ + uint8_t playback : 1; /*When the animation is ready play it back*/ + uint8_t repeat : 1; /*Repeat the animation infinitely*/ + /*Animation system use these - user shouldn't set*/ + uint8_t playback_now : 1; /*Play back is in progress*/ +} lv_anim_t; + +/*Example initialization +lv_anim_t a; +a.var = obj; +a.start = lv_obj_get_height(obj); +a.end = new_height; +a.fp = (lv_anim_fp_t)lv_obj_set_height; +a.path = lv_anim_path_linear; +a.end_cb = NULL; +a.act_time = 0; +a.time = 200; +a.playback = 0; +a.playback_pause = 0; +a.repeat = 0; +a.repeat_pause = 0; + */ +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init. the animation module + */ +void lv_anim_init(void); + +/** + * Create an animation + * @param anim_p an initialized 'anim_t' variable. Not required after call. + */ +void lv_anim_create(lv_anim_t *anim_p); + +/** + * Delete an animation for a variable with a given animatior function + * @param var pointer to variable + * @param fp a function pointer which is animating 'var', + * or NULL to ignore it and delete all animation with 'var + * @return true: at least 1 animation is deleted, false: no animation is deleted + */ +bool lv_anim_del(void *var, lv_anim_fp_t fp); + +/** + * Calculate the time of an animation with a given speed and the start and end + * values + * @param speed speed of animation in unit/sec + * @param start start value of the animation + * @param end end value of the animation + * @return the required time [ms] for the animation with the given parameters + */ +uint16_t lv_anim_speed_to_time(uint16_t speed, int32_t start, int32_t end); + +/** + * Calculate the current value of an animation applying linear characteristic + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_linear(const lv_anim_t *a); + +/** + * Calculate the current value of an animation applying step characteristic. + * (Set end value on the end of the animation) + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_step(const lv_anim_t *a); +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_ANIMATION == 0*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ANIM_H*/ diff --git a/include/display/lv_misc/lv_area.h b/include/display/lv_misc/lv_area.h new file mode 100644 index 0000000..4366b37 --- /dev/null +++ b/include/display/lv_misc/lv_area.h @@ -0,0 +1,166 @@ +/** + * @file lv_area.h + * + */ + +#ifndef LV_AREA_H +#define LV_AREA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include + +/********************* + * DEFINES + *********************/ +#define LV_COORD_MAX \ + (16383) /*To avoid overflow don't let the max [-32,32k] range */ +#define LV_COORD_MIN (-16384) + +/********************** + * TYPEDEFS + **********************/ +typedef int16_t lv_coord_t; + +typedef struct { + lv_coord_t x; + lv_coord_t y; +} lv_point_t; + +typedef struct { + lv_coord_t x1; + lv_coord_t y1; + lv_coord_t x2; + lv_coord_t y2; +} lv_area_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an area + * @param area_p pointer to an area + * @param x1 left coordinate of the area + * @param y1 top coordinate of the area + * @param x2 right coordinate of the area + * @param y2 bottom coordinate of the area + */ +void lv_area_set(lv_area_t *area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, + lv_coord_t y2); + +/** + * Copy an area + * @param dest pointer to the destination area + * @param src pointer to the source area + */ +inline static void lv_area_copy(lv_area_t *dest, const lv_area_t *src) { + memcpy(dest, src, sizeof(lv_area_t)); +} + +/** + * Get the width of an area + * @param area_p pointer to an area + * @return the width of the area (if x1 == x2 -> width = 1) + */ +static inline lv_coord_t lv_area_get_width(const lv_area_t *area_p) { + return area_p->x2 - area_p->x1 + 1; +} + +/** + * Get the height of an area + * @param area_p pointer to an area + * @return the height of the area (if y1 == y2 -> height = 1) + */ +static inline lv_coord_t lv_area_get_height(const lv_area_t *area_p) { + return area_p->y2 - area_p->y1 + 1; +} + +/** + * Set the width of an area + * @param area_p pointer to an area + * @param w the new width of the area (w == 1 makes x1 == x2) + */ +void lv_area_set_width(lv_area_t *area_p, lv_coord_t w); + +/** + * Set the height of an area + * @param area_p pointer to an area + * @param h the new height of the area (h == 1 makes y1 == y2) + */ +void lv_area_set_height(lv_area_t *area_p, lv_coord_t h); + +/** + * Set the position of an area (width and height will be kept) + * @param area_p pointer to an area + * @param x the new x coordinate of the area + * @param y the new y coordinate of the area + */ +void lv_area_set_pos(lv_area_t *area_p, lv_coord_t x, lv_coord_t y); + +/** + * Return with area of an area (x * y) + * @param area_p pointer to an area + * @return size of area + */ +uint32_t lv_area_get_size(const lv_area_t *area_p); + +/** + * Get the common parts of two areas + * @param res_p pointer to an area, the result will be stored her + * @param a1_p pointer to the first area + * @param a2_p pointer to the second area + * @return false: the two area has NO common parts, res_p is invalid + */ +bool lv_area_union(lv_area_t *res_p, const lv_area_t *a1_p, + const lv_area_t *a2_p); + +/** + * Join two areas into a third which involves the other two + * @param res_p pointer to an area, the result will be stored here + * @param a1_p pointer to the first area + * @param a2_p pointer to the second area + */ +void lv_area_join(lv_area_t *a_res_p, const lv_area_t *a1_p, + const lv_area_t *a2_p); + +/** + * Check if a point is on an area + * @param a_p pointer to an area + * @param p_p pointer to a point + * @return false:the point is out of the area + */ +bool lv_area_is_point_on(const lv_area_t *a_p, const lv_point_t *p_p); + +/** + * Check if two area has common parts + * @param a1_p pointer to an area. + * @param a2_p pointer to an other area + * @return false: a1_p and a2_p has no common parts + */ +bool lv_area_is_on(const lv_area_t *a1_p, const lv_area_t *a2_p); + +/** + * Check if an area is fully on an other + * @param ain_p pointer to an area which could be on aholder_p + * @param aholder pointer to an area which could involve ain_p + * @return + */ +bool lv_area_is_in(const lv_area_t *ain_p, const lv_area_t *aholder_p); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_circ.h b/include/display/lv_misc/lv_circ.h new file mode 100644 index 0000000..411f440 --- /dev/null +++ b/include/display/lv_misc/lv_circ.h @@ -0,0 +1,77 @@ +/** + * @file lv_circ.h + * + */ + +#ifndef LV_CIRC_H +#define LV_CIRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_area.h" +#include + +/********************* + * DEFINES + *********************/ +#define LV_CIRC_OCT1_X(p) (p.x) +#define LV_CIRC_OCT1_Y(p) (p.y) +#define LV_CIRC_OCT2_X(p) (p.y) +#define LV_CIRC_OCT2_Y(p) (p.x) +#define LV_CIRC_OCT3_X(p) (-p.y) +#define LV_CIRC_OCT3_Y(p) (p.x) +#define LV_CIRC_OCT4_X(p) (-p.x) +#define LV_CIRC_OCT4_Y(p) (p.y) +#define LV_CIRC_OCT5_X(p) (-p.x) +#define LV_CIRC_OCT5_Y(p) (-p.y) +#define LV_CIRC_OCT6_X(p) (-p.y) +#define LV_CIRC_OCT6_Y(p) (-p.x) +#define LV_CIRC_OCT7_X(p) (p.y) +#define LV_CIRC_OCT7_Y(p) (-p.x) +#define LV_CIRC_OCT8_X(p) (p.x) +#define LV_CIRC_OCT8_Y(p) (-p.y) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the circle drawing + * @param c pointer to a point. The coordinates will be calculated here + * @param tmp point to a variable. It will store temporary data + * @param radius radius of the circle + */ +void lv_circ_init(lv_point_t *c, lv_coord_t *tmp, lv_coord_t radius); + +/** + * Test the circle drawing is ready or not + * @param c same as in circ_init + * @return true if the circle is not ready yet + */ +bool lv_circ_cont(lv_point_t *c); + +/** + * Get the next point from the circle + * @param c same as in circ_init. The next point stored here. + * @param tmp same as in circ_init. + */ +void lv_circ_next(lv_point_t *c, lv_coord_t *tmp); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_color.h b/include/display/lv_misc/lv_color.h new file mode 100644 index 0000000..0dad679 --- /dev/null +++ b/include/display/lv_misc/lv_color.h @@ -0,0 +1,325 @@ +/** + * @file lv_color.h + * + */ + +#ifndef LV_COLOR_H +#define LV_COLOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#include + +/********************* + * DEFINES + *********************/ +#define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00) +#define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF) +#define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00) +#define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00) +#define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF) +#define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00) +#define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF) +#define LV_COLOR_AQUA LV_COLOR_CYAN +#define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF, 0x00, 0xFF) +#define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0) +#define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80) +#define LV_COLOR_MARRON LV_COLOR_MAKE(0x80, 0x00, 0x00) +#define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00) +#define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00) +#define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80) +#define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80) +#define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80) +#define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00) + +#define LV_OPA_TRANSP 0 +#define LV_OPA_0 0 +#define LV_OPA_10 25 +#define LV_OPA_20 51 +#define LV_OPA_30 76 +#define LV_OPA_40 102 +#define LV_OPA_50 127 +#define LV_OPA_60 153 +#define LV_OPA_70 178 +#define LV_OPA_80 204 +#define LV_OPA_90 229 +#define LV_OPA_100 255 +#define LV_OPA_COVER 255 + +/********************** + * TYPEDEFS + **********************/ + +typedef union { + uint8_t blue : 1; + uint8_t green : 1; + uint8_t red : 1; + uint8_t full : 1; +} lv_color1_t; + +typedef union { + struct { + uint8_t blue : 2; + uint8_t green : 3; + uint8_t red : 3; + }; + uint8_t full; +} lv_color8_t; + +typedef union { + struct { + uint16_t blue : 5; + uint16_t green : 6; + uint16_t red : 5; + }; + uint16_t full; +} lv_color16_t; + +typedef union { + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + uint32_t full; +} lv_color24_t; + +#if LV_COLOR_DEPTH == 1 +typedef uint8_t lv_color_int_t; +typedef lv_color1_t lv_color_t; +#elif LV_COLOR_DEPTH == 8 +typedef uint8_t lv_color_int_t; +typedef lv_color8_t lv_color_t; +#elif LV_COLOR_DEPTH == 16 +typedef uint16_t lv_color_int_t; +typedef lv_color16_t lv_color_t; +#elif LV_COLOR_DEPTH == 24 +typedef uint32_t lv_color_int_t; +typedef lv_color24_t lv_color_t; +#else +#error "Invalid LV_COLOR_DEPTH in misc_conf.h! Set it to 1, 8, 16 or 24!" +#endif + +typedef uint8_t lv_opa_t; + +typedef struct { + uint16_t h; + uint8_t s; + uint8_t v; +} lv_color_hsv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*In color conversations: + * - When converting to bigger color type the LSB weight of 1 LSB is calculated + * E.g. 16 bit Red has 5 bits + * 8 bit Red has 2 bits + * ---------------------- + * 8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10 + * + * - When calculating to smaller color type simply shift out the LSBs + * E.g. 8 bit Red has 2 bits + * 16 bit Red has 5 bits + * ---------------------- + * Shift right with 5 - 3 = 2 + */ + +static inline uint8_t lv_color_to1(lv_color_t color) { +#if LV_COLOR_DEPTH == 1 + return color.full; +#elif LV_COLOR_DEPTH == 8 + if ((color.red & 0x4) || (color.green & 0x4) || (color.blue & 0x2)) { + return 1; + } else { + return 0; + } +#elif LV_COLOR_DEPTH == 16 + if ((color.red & 0x10) || (color.green & 0x20) || (color.blue & 0x10)) { + return 1; + } else { + return 0; + } +#elif LV_COLOR_DEPTH == 24 + if ((color.red & 0x80) || (color.green & 0x80) || (color.blue & 0x80)) { + return 1; + } else { + return 0; + } +#endif +} + +static inline uint8_t lv_color_to8(lv_color_t color) { +#if LV_COLOR_DEPTH == 1 + if (color.full == 0) + return 0; + else + return 0xFF; +#elif LV_COLOR_DEPTH == 8 + return color.full; +#elif LV_COLOR_DEPTH == 16 + lv_color8_t ret; + ret.red = color.red >> 2; /* 5 - 3 = 2*/ + ret.green = color.green >> 3; /* 6 - 3 = 3*/ + ret.blue = color.blue >> 3; /* 5 - 2 = 3*/ + return ret.full; +#elif LV_COLOR_DEPTH == 24 + lv_color8_t ret; + ret.red = color.red >> 5; /* 8 - 3 = 5*/ + ret.green = color.green >> 5; /* 8 - 3 = 5*/ + ret.blue = color.blue >> 6; /* 8 - 2 = 6*/ + return ret.full; +#endif +} + +static inline uint16_t lv_color_to16(lv_color_t color) { +#if LV_COLOR_DEPTH == 1 + if (color.full == 0) + return 0; + else + return 0xFFFF; +#elif LV_COLOR_DEPTH == 8 + lv_color16_t ret; + ret.red = color.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ + ret.green = color.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ + ret.blue = color.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ + return ret.full; +#elif LV_COLOR_DEPTH == 16 + return color.full; +#elif LV_COLOR_DEPTH == 24 + lv_color16_t ret; + ret.red = color.red >> 3; /* 8 - 5 = 3*/ + ret.green = color.green >> 2; /* 8 - 6 = 2*/ + ret.blue = color.blue >> 3; /* 8 - 5 = 3*/ + return ret.full; +#endif +} + +static inline uint32_t lv_color_to24(lv_color_t color) { +#if LV_COLOR_DEPTH == 1 + if (color.full == 0) + return 0; + else + return 0xFFFFFFFF; +#elif LV_COLOR_DEPTH == 8 + lv_color24_t ret; + ret.red = color.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ + ret.green = color.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ + ret.blue = color.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ + ret.alpha = 0xFF; + return ret.full; +#elif LV_COLOR_DEPTH == 16 + lv_color24_t ret; + ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ + ret.green = color.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ + ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ + ret.alpha = 0xFF; + return ret.full; +#elif LV_COLOR_DEPTH == 24 + return color.full; +#endif +} + +static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, + uint8_t mix) { + lv_color_t ret; +#if LV_COLOR_DEPTH != 1 + ret.red = (uint16_t)((uint16_t)c1.red * mix + (c2.red * (255 - mix))) >> 8; + ret.green = + (uint16_t)((uint16_t)c1.green * mix + (c2.green * (255 - mix))) >> 8; + ret.blue = (uint16_t)((uint16_t)c1.blue * mix + (c2.blue * (255 - mix))) >> 8; +#if LV_COLOR_DEPTH == 24 + ret.alpha = 0xFF; +#endif +#else + ret.full = mix > LV_OPA_50 ? c1.full : c2.full; +#endif + + return ret; +} + +/** + * Get the brightness of a color + * @param color a color + * @return the brightness [0..255] + */ +static inline uint8_t lv_color_brightness(lv_color_t color) { + lv_color24_t c24; + c24.full = lv_color_to24(color); + uint16_t bright = 3 * c24.red + c24.blue + 4 * c24.green; + return (uint16_t)bright >> 3; +} + +/* The most simple macro to create a color from R,G and B values + * The order of bit field is different on Big-endian and Little-endian + * machines*/ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#if LV_COLOR_DEPTH == 1 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(b8 >> 7 | g8 >> 7 | r8 >> 7)}) +#elif LV_COLOR_DEPTH == 8 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}}) +#elif LV_COLOR_DEPTH == 16 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}}) +#elif LV_COLOR_DEPTH == 24 +#define LV_COLOR_MAKE(r8, g8, b8) \ + ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/ +#endif +#else +#if LV_COLOR_DEPTH == 1 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(r8 >> 7 | g8 >> 7 | b8 >> 7)}) +#elif LV_COLOR_DEPTH == 8 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{r8 >> 6, g8 >> 5, b8 >> 5}}) +#elif LV_COLOR_DEPTH == 16 +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{r8 >> 3, g8 >> 2, b8 >> 3}}) +#elif LV_COLOR_DEPTH == 24 +#define LV_COLOR_MAKE(r8, g8, b8) \ + ((lv_color_t){{0xff, r8, g8, b8}}) /*Fix 0xff alpha*/ +#endif +#endif + +#define LV_COLOR_HEX(c) \ + LV_COLOR_MAKE(((uint32_t)((uint32_t)c >> 16) & 0xFF), \ + ((uint32_t)((uint32_t)c >> 8) & 0xFF), ((uint32_t)c & 0xFF)) + +/*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/ +#define LV_COLOR_HEX3(c) \ + LV_COLOR_MAKE((((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), \ + ((uint32_t)(c & 0xF0) | ((c & 0xF0) >> 4)), \ + ((uint32_t)(c & 0xF) | ((c & 0xF) << 4))) + +/** + * Convert a HSV color to RGB + * @param h hue [0..359] + * @param s saturation [0..100] + * @param v value [0..100] + * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth) + */ +lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v); + +/** + * Convert an RGB color to HSV + * @param r red + * @param g green + * @param b blue + * @return the given RGB color n HSV + */ +lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*USE_COLOR*/ diff --git a/include/display/lv_misc/lv_font.h b/include/display/lv_misc/lv_font.h new file mode 100644 index 0000000..7eb8133 --- /dev/null +++ b/include/display/lv_misc/lv_font.h @@ -0,0 +1,251 @@ +/** + * @file lv_font.h + * + */ + +#ifndef LV_FONT_H +#define LV_FONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#include +#include + +#include "lv_fonts/lv_symbol_def.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint32_t w_px : 8; + uint32_t glyph_index : 24; +} lv_font_glyph_dsc_t; + +typedef struct { + uint32_t unicode : 21; + uint32_t glyph_dsc_index : 11; +} lv_font_unicode_map_t; + +typedef struct _lv_font_struct { + uint32_t unicode_first; + uint32_t unicode_last; + uint8_t h_px; + const uint8_t *glyph_bitmap; + const lv_font_glyph_dsc_t *glyph_dsc; + const uint32_t *unicode_list; + const uint8_t *(*get_bitmap)(const struct _lv_font_struct *, + uint32_t); /*Get a glyph's bitmap from a font*/ + const int16_t (*get_width)(const struct _lv_font_struct *, + uint32_t); /*Get a glyph's with with a given font*/ + struct _lv_font_struct *next_page; /*Pointer to a font extension*/ + uint32_t bpp : 4; /*Bit per pixel: 1, 2 or 4*/ +} lv_font_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the built-in fonts + */ +void lv_font_init(void); + +/** + * Create a pair from font name and font dsc. get function. After it 'font_get' + * can be used for this font + * @param child pointer to a font to join to the 'parent' + * @param parent pointer to a font. 'child' will be joined here + */ +void lv_font_add(lv_font_t *child, lv_font_t *parent); + +/** + * Return with the bitmap of a font. + * @param font_p pointer to a font + * @param letter a letter + * @return pointer to the bitmap of the letter + */ +const uint8_t *lv_font_get_bitmap(const lv_font_t *font_p, uint32_t letter); + +/** + * Get the height of a font + * @param font_p pointer to a font + * @return the height of a font + */ +static inline uint8_t lv_font_get_height(const lv_font_t *font_p) { + return font_p->h_px; +} + +/** + * Get the width of a letter in a font + * @param font_p pointer to a font + * @param letter a letter + * @return the width of a letter + */ +uint8_t lv_font_get_width(const lv_font_t *font_p, uint32_t letter); + +/** + * Get the bit-per-pixel of font + * @param font pointer to font + * @param letter a letter from font (font extensions can have different bpp) + * @return bpp of the font (or font extension) + */ +uint8_t lv_font_get_bpp(const lv_font_t *font, uint32_t letter); + +/** + * Generic bitmap get function used in 'font->get_bitmap' when the font contains + * all characters in the range + * @param font pointer to font + * @param unicode_letter an unicode letter which bitmap should be get + * @return pointer to the bitmap or NULL if not found + */ +const uint8_t *lv_font_get_bitmap_continuous(const lv_font_t *font, + uint32_t unicode_letter); + +/** + * Generic bitmap get function used in 'font->get_bitmap' when the font NOT + * contains all characters in the range (sparse) + * @param font pointer to font + * @param unicode_letter an unicode letter which bitmap should be get + * @return pointer to the bitmap or NULL if not found + */ +const uint8_t *lv_font_get_bitmap_sparse(const lv_font_t *font, + uint32_t unicode_letter); +/** + * Generic glyph width get function used in 'font->get_width' when the font + * contains all characters in the range + * @param font pointer to font + * @param unicode_letter an unicode letter which width should be get + * @return width of the gylph or -1 if not found + */ +const int16_t lv_font_get_width_continuous(const lv_font_t *font, + uint32_t unicode_letter); + +/** + * Generic glyph width get function used in 'font->get_bitmap' when the font NOT + * contains all characters in the range (sparse) + * @param font pointer to font + * @param unicode_letter an unicode letter which width should be get + * @return width of the glyph or -1 if not found + */ +const int16_t lv_font_get_width_sparse(const lv_font_t *font, + uint32_t unicode_letter); + +/********************** + * MACROS + **********************/ +#define LV_FONT_DECLARE(font_name) extern lv_font_t font_name; + +/****************************** + * FONT DECLARATION INCLUDES + *****************************/ + +/*10 px */ +#if USE_LV_FONT_DEJAVU_10 +LV_FONT_DECLARE(lv_font_dejavu_10) +#endif + +#if USE_LV_FONT_DEJAVU_10_LATIN_SUP +LV_FONT_DECLARE(lv_font_dejavu_10_latin_sup) +#endif + +#if USE_LV_FONT_DEJAVU_10_CYRILLIC +LV_FONT_DECLARE(lv_font_dejavu_10_cyrillic) +#endif + +#if USE_LV_FONT_SYMBOL_10 +LV_FONT_DECLARE(lv_font_symbol_10) +#endif + +/*20 px */ +#if USE_LV_FONT_DEJAVU_20 +LV_FONT_DECLARE(lv_font_dejavu_20) +#endif + +#if USE_LV_FONT_DEJAVU_20_LATIN_SUP +LV_FONT_DECLARE(lv_font_dejavu_20_latin_sup) +#endif + +#if USE_LV_FONT_DEJAVU_20_CYRILLIC +LV_FONT_DECLARE(lv_font_dejavu_20_cyrillic) +#endif + +#if USE_LV_FONT_SYMBOL_20 +LV_FONT_DECLARE(lv_font_symbol_20) +#endif + +/*30 px */ +#if USE_LV_FONT_DEJAVU_30 +LV_FONT_DECLARE(lv_font_dejavu_30) +#endif + +#if USE_LV_FONT_DEJAVU_30_LATIN_SUP +LV_FONT_DECLARE(lv_font_dejavu_30_latin_sup) +#endif + +#if USE_LV_FONT_DEJAVU_30_CYRILLIC +LV_FONT_DECLARE(lv_font_dejavu_30_cyrillic) +#endif + +#if USE_LV_FONT_SYMBOL_30 +LV_FONT_DECLARE(lv_font_symbol_30) +#endif + +/*40 px */ +#if USE_LV_FONT_DEJAVU_40 +LV_FONT_DECLARE(lv_font_dejavu_40) +#endif + +#if USE_LV_FONT_DEJAVU_40_LATIN_SUP +LV_FONT_DECLARE(lv_font_dejavu_40_latin_sup) +#endif + +#if USE_LV_FONT_DEJAVU_40_CYRILLIC +LV_FONT_DECLARE(lv_font_dejavu_40_cyrillic) +#endif + +#if USE_PROS_FONT_DEJAVU_MONO_10 +LV_FONT_DECLARE(pros_font_dejavu_mono_10) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_10_LATIN_SUP +LV_FONT_DECLARE(pros_font_dejavu_mono_10_latin_sup) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_20 +LV_FONT_DECLARE(pros_font_dejavu_mono_20) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_20_LATIN_SUP +LV_FONT_DECLARE(pros_font_dejavu_mono_20_latin_sup) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_30 +LV_FONT_DECLARE(pros_font_dejavu_mono_30) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_30_LATIN_SUP +LV_FONT_DECLARE(pros_font_dejavu_mono_30_latin_sup) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_40 +LV_FONT_DECLARE(pros_font_dejavu_mono_40) +#endif +#if USE_PROS_FONT_DEJAVU_MONO_40_LATIN_SUP +LV_FONT_DECLARE(pros_font_dejavu_mono_40_latin_sup) +#endif + +#if USE_LV_FONT_SYMBOL_40 +LV_FONT_DECLARE(lv_font_symbol_40) +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*USE_FONT*/ diff --git a/include/display/lv_misc/lv_fonts/lv_fonts.mk b/include/display/lv_misc/lv_fonts/lv_fonts.mk new file mode 100644 index 0000000..936301a --- /dev/null +++ b/include/display/lv_misc/lv_fonts/lv_fonts.mk @@ -0,0 +1,21 @@ +CSRCS += lv_font_dejavu_10.c +CSRCS += lv_font_dejavu_20.c +CSRCS += lv_font_dejavu_30.c +CSRCS += lv_font_dejavu_40.c +CSRCS += lv_font_dejavu_10_cyrillic.c +CSRCS += lv_font_dejavu_20_cyrillic.c +CSRCS += lv_font_dejavu_30_cyrillic.c +CSRCS += lv_font_dejavu_40_cyrillic.c +CSRCS += lv_font_dejavu_10_latin_sup.c +CSRCS += lv_font_dejavu_20_latin_sup.c +CSRCS += lv_font_dejavu_30_latin_sup.c +CSRCS += lv_font_dejavu_40_latin_sup.c +CSRCS += lv_font_symbol_10.c +CSRCS += lv_font_symbol_20.c +CSRCS += lv_font_symbol_30.c +CSRCS += lv_font_symbol_40.c + +DEPPATH += --dep-path lvgl/lv_misc/lv_fonts +VPATH += :lvgl/lv_misc/lv_fonts + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_misc/lv_fonts" diff --git a/include/display/lv_misc/lv_fonts/lv_symbol_def.h b/include/display/lv_misc/lv_fonts/lv_symbol_def.h new file mode 100644 index 0000000..f536baf --- /dev/null +++ b/include/display/lv_misc/lv_fonts/lv_symbol_def.h @@ -0,0 +1,134 @@ +#ifndef LV_SYMBOL_DEF_H +#define LV_SYMBOL_DEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "display/lv_conf.h" + +/* + * With no UTF-8 support (192-255) + * - Basic symbols: 0xC0..0xCF + * - Feedback symbols: 0xD0..0xDF + * - File symbols: 0xE0..0xFF + * + * With UTF-8 support (in Supplemental Private Use Area-A) + * - Basic symbols: 0xE000..0xE01F + * - File symbols: 0xE020..0xE03F + * - Feedback symbols: 0xE040..0xE05F + * - Reserved: 0xE060..0xE07F + */ + +#if LV_TXT_UTF8 == 0 +#define LV_SYMBOL_GLYPH_FIRST 0xC0 +#define SYMBOL_AUDIO "\xC0" +#define SYMBOL_VIDEO "\xC1" +#define SYMBOL_LIST "\xC2" +#define SYMBOL_OK "\xC3" +#define SYMBOL_CLOSE "\xC4" +#define SYMBOL_POWER "\xC5" +#define SYMBOL_SETTINGS "\xC6" +#define SYMBOL_TRASH "\xC7" +#define SYMBOL_HOME "\xC8" +#define SYMBOL_DOWNLOAD "\xC9" +#define SYMBOL_DRIVE "\xCA" +#define SYMBOL_REFRESH "\xCB" +#define SYMBOL_MUTE "\xCC" +#define SYMBOL_VOLUME_MID "\xCD" +#define SYMBOL_VOLUME_MAX "\xCE" +#define SYMBOL_IMAGE "\xCF" +#define SYMBOL_EDIT "\xD0" +#define SYMBOL_PREV "\xD1" +#define SYMBOL_PLAY "\xD2" +#define SYMBOL_PAUSE "\xD3" +#define SYMBOL_STOP "\xD4" +#define SYMBOL_NEXT "\xD5" +#define SYMBOL_EJECT "\xD6" +#define SYMBOL_LEFT "\xD7" +#define SYMBOL_RIGHT "\xD8" +#define SYMBOL_PLUS "\xD9" +#define SYMBOL_MINUS "\xDA" +#define SYMBOL_WARNING "\xDB" +#define SYMBOL_SHUFFLE "\xDC" +#define SYMBOL_UP "\xDD" +#define SYMBOL_DOWN "\xDE" +#define SYMBOL_LOOP "\xDF" +#define SYMBOL_DIRECTORY "\xE0" +#define SYMBOL_UPLOAD "\xE1" +#define SYMBOL_CALL "\xE2" +#define SYMBOL_CUT "\xE3" +#define SYMBOL_COPY "\xE4" +#define SYMBOL_SAVE "\xE5" +#define SYMBOL_CHARGE "\xE6" +#define SYMBOL_BELL "\xE7" +#define SYMBOL_KEYBOARD "\xE8" +#define SYMBOL_GPS "\xE9" +#define SYMBOL_FILE "\xEA" +#define SYMBOL_WIFI "\xEB" +#define SYMBOL_BATTERY_FULL "\xEC" +#define SYMBOL_BATTERY_3 "\xED" +#define SYMBOL_BATTERY_2 "\xEE" +#define SYMBOL_BATTERY_1 "\xEF" +#define SYMBOL_BATTERY_EMPTY "\xF0" +#define SYMBOL_BLUETOOTH "\xF1" +#else +#define LV_SYMBOL_GLYPH_FIRST 0xF000 + +#define SYMBOL_AUDIO "\xEF\x80\x80" +#define SYMBOL_VIDEO "\xEF\x80\x81" +#define SYMBOL_LIST "\xEF\x80\x82" +#define SYMBOL_OK "\xEF\x80\x83" +#define SYMBOL_CLOSE "\xEF\x80\x84" +#define SYMBOL_POWER "\xEF\x80\x85" +#define SYMBOL_SETTINGS "\xEF\x80\x86" +#define SYMBOL_TRASH "\xEF\x80\x87" +#define SYMBOL_HOME "\xEF\x80\x88" +#define SYMBOL_DOWNLOAD "\xEF\x80\x89" +#define SYMBOL_DRIVE "\xEF\x80\x8A" +#define SYMBOL_REFRESH "\xEF\x80\x8B" +#define SYMBOL_MUTE "\xEF\x80\x8C" +#define SYMBOL_VOLUME_MID "\xEF\x80\x8D" +#define SYMBOL_VOLUME_MAX "\xEF\x80\x8E" +#define SYMBOL_IMAGE "\xEF\x80\x8F" +#define SYMBOL_EDIT "\xEF\x80\x90" +#define SYMBOL_PREV "\xEF\x80\x91" +#define SYMBOL_PLAY "\xEF\x80\x92" +#define SYMBOL_PAUSE "\xEF\x80\x93" +#define SYMBOL_STOP "\xEF\x80\x94" +#define SYMBOL_NEXT "\xEF\x80\x95" +#define SYMBOL_EJECT "\xEF\x80\x96" +#define SYMBOL_LEFT "\xEF\x80\x97" +#define SYMBOL_RIGHT "\xEF\x80\x98" +#define SYMBOL_PLUS "\xEF\x80\x99" +#define SYMBOL_MINUS "\xEF\x80\x9A" +#define SYMBOL_WARNING "\xEF\x80\x9B" +#define SYMBOL_SHUFFLE "\xEF\x80\x9C" +#define SYMBOL_UP "\xEF\x80\x9D" +#define SYMBOL_DOWN "\xEF\x80\x9E" +#define SYMBOL_LOOP "\xEF\x80\x9F" +#define SYMBOL_DIRECTORY "\xEF\x80\xA0" +#define SYMBOL_UPLOAD "\xEF\x80\xA1" +#define SYMBOL_CALL "\xEF\x80\xA2" +#define SYMBOL_CUT "\xEF\x80\xA3" +#define SYMBOL_COPY "\xEF\x80\xA4" +#define SYMBOL_SAVE "\xEF\x80\xA5" +#define SYMBOL_CHARGE "\xEF\x80\xA6" +#define SYMBOL_BELL "\xEF\x80\xA7" +#define SYMBOL_KEYBOARD "\xEF\x80\xA8" +#define SYMBOL_GPS "\xEF\x80\xA9" +#define SYMBOL_FILE "\xEF\x80\xAA" +#define SYMBOL_WIFI "\xEF\x80\xAB" +#define SYMBOL_BATTERY_FULL "\xEF\x80\xAC" +#define SYMBOL_BATTERY_3 "\xEF\x80\xAD" +#define SYMBOL_BATTERY_2 "\xEF\x80\xAE" +#define SYMBOL_BATTERY_1 "\xEF\x80\xAF" +#define SYMBOL_BATTERY_EMPTY "\xEF\x80\xB0" +#define SYMBOL_BLUETOOTH "\xEF\x80\xB1" +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_SYMBOL_DEF_H*/ diff --git a/include/display/lv_misc/lv_fs.h b/include/display/lv_misc/lv_fs.h new file mode 100644 index 0000000..5ad6243 --- /dev/null +++ b/include/display/lv_misc/lv_fs.h @@ -0,0 +1,248 @@ +/** + * @file lv_fs.h + * + */ + +#ifndef LV_FS_H +#define LV_FS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if USE_LV_FILESYSTEM + +#include "lv_mem.h" +#include +#include + +/********************* + * DEFINES + *********************/ +#define LV_FS_MAX_FN_LENGTH 64 + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_FS_RES_OK = 0, + LV_FS_RES_HW_ERR, /*Low level hardware error*/ + LV_FS_RES_FS_ERR, /*Error in the file system structure */ + LV_FS_RES_NOT_EX, /*Driver, file or directory is not exists*/ + LV_FS_RES_FULL, /*Disk full*/ + LV_FS_RES_LOCKED, /*The file is already opened*/ + LV_FS_RES_DENIED, /*Access denied. Check 'fs_open' modes and write protect*/ + LV_FS_RES_BUSY, /*The file system now can't handle it, try later*/ + LV_FS_RES_TOUT, /*Process time outed*/ + LV_FS_RES_NOT_IMP, /*Requested function is not implemented*/ + LV_FS_RES_OUT_OF_MEM, /*Not enough memory for an internal operation*/ + LV_FS_RES_INV_PARAM, /*Invalid parameter among arguments*/ + LV_FS_RES_UNKNOWN, /*Other unknown error*/ +} lv_fs_res_t; + +struct __lv_fs_drv_t; + +typedef struct { + void *file_d; + struct __lv_fs_drv_t *drv; +} lv_fs_file_t; + +typedef struct { + void *dir_d; + struct __lv_fs_drv_t *drv; +} lv_fs_dir_t; + +typedef enum { + LV_FS_MODE_WR = 0x01, + LV_FS_MODE_RD = 0x02, +} lv_fs_mode_t; + +typedef struct __lv_fs_drv_t { + char letter; + uint16_t file_size; + uint16_t rddir_size; + bool (*ready)(void); + + lv_fs_res_t (*open)(void *file_p, const char *path, lv_fs_mode_t mode); + lv_fs_res_t (*close)(void *file_p); + lv_fs_res_t (*remove)(const char *fn); + lv_fs_res_t (*read)(void *file_p, void *buf, uint32_t btr, uint32_t *br); + lv_fs_res_t (*write)(void *file_p, const void *buf, uint32_t btw, + uint32_t *bw); + lv_fs_res_t (*seek)(void *file_p, uint32_t pos); + lv_fs_res_t (*tell)(void *file_p, uint32_t *pos_p); + lv_fs_res_t (*trunc)(void *file_p); + lv_fs_res_t (*size)(void *file_p, uint32_t *size_p); + lv_fs_res_t (*free)(uint32_t *total_p, uint32_t *free_p); + + lv_fs_res_t (*dir_open)(void *rddir_p, const char *path); + lv_fs_res_t (*dir_read)(void *rddir_p, char *fn); + lv_fs_res_t (*dir_close)(void *rddir_p); +} lv_fs_drv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the File system interface + */ +void lv_fs_init(void); + +/** + * Add a new drive + * @param drv_p pointer to an lv_fs_drv_t structure which is inited with the + * corresponding function pointers. The data will be copied so the variable can + * be local. + */ +void lv_fs_add_drv(lv_fs_drv_t *drv_p); + +/** + * Open a file + * @param file_p pointer to a lv_fs_file_t variable + * @param path path to the file beginning with the driver letter (e.g. + * S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | + * FS_MODE_WR + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_open(lv_fs_file_t *file_p, const char *path, + lv_fs_mode_t mode); + +/** + * Close an already opened file + * @param file_p pointer to a lv_fs_file_t variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_close(lv_fs_file_t *file_p); + +/** + * Delete a file + * @param path path of the file to delete + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_remove(const char *path); + +/** + * Read from a file + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer where the read bytes are stored + * @param btr Bytes To Read + * @param br the number of real read bytes (Bytes Read). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_read(lv_fs_file_t *file_p, void *buf, uint32_t btr, + uint32_t *br); + +/** + * Write into a file + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_write(lv_fs_file_t *file_p, const void *buf, uint32_t btw, + uint32_t *bw); + +/** + * Set the position of the 'cursor' (read write pointer) in a file + * @param file_p pointer to a lv_fs_file_t variable + * @param pos the new position expressed in bytes index (0: start of file) + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_seek(lv_fs_file_t *file_p, uint32_t pos); + +/** + * Give the position of the read write pointer + * @param file_p pointer to a lv_fs_file_t variable + * @param pos_p pointer to store the position of the read write pointer + * @return LV_FS_RES_OK or any error from 'fs_res_t' + */ +lv_fs_res_t lv_fs_tell(lv_fs_file_t *file_p, uint32_t *pos); + +/** + * Give the size of a file bytes + * @param file_p pointer to a lv_fs_file_t variable + * @param size pointer to a variable to store the size + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_size(lv_fs_file_t *file_p, uint32_t *size); + +/** + * Initialize a 'fs_dir_t' variable for directory reading + * @param rddir_p pointer to a 'fs_read_dir_t' variable + * @param path path to a directory + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t *rddir_p, const char *path); + +/** + * Read the next filename form a directory. + * The name of the directories will begin with '/' + * @param rddir_p pointer to an initialized 'fs_rdir_t' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t *rddir_p, char *fn); + +/** + * Close the directory reading + * @param rddir_p pointer to an initialized 'fs_dir_t' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t *rddir_p); + +/** + * Get the free and total size of a driver in kB + * @param letter the driver letter + * @param total_p pointer to store the total size [kB] + * @param free_p pointer to store the free size [kB] + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_free(char letter, uint32_t *total_p, uint32_t *free_p); + +/** + * Fill a buffer with the letters of existing drivers + * @param buf buffer to store the letters ('\0' added after the last letter) + * @return the buffer + */ +char *lv_fs_get_letters(char *buf); + +/** + * Return with the extension of the filename + * @param fn string with a filename + * @return pointer to the beginning extension or empty string if no extension + */ +const char *lv_fs_get_ext(const char *fn); + +/** + * Step up one level + * @param path pointer to a file name + * @return the truncated file name + */ +char *lv_fs_up(char *path); + +/** + * Get the last element of a path (e.g. U:/folder/file -> file) + * @param buf buffer to store the letters ('\0' added after the last letter) + * @return pointer to the beginning of the last element in the path + */ +const char *lv_fs_get_last(const char *path); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_FILESYSTEM*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_FS_H*/ diff --git a/include/display/lv_misc/lv_ll.h b/include/display/lv_misc/lv_ll.h new file mode 100644 index 0000000..0c5cf78 --- /dev/null +++ b/include/display/lv_misc/lv_ll.h @@ -0,0 +1,139 @@ +/** + * @file lv_ll.c + * Handle linked lists. The nodes are dynamically allocated by the 'lv_mem' + * module. + */ + +#ifndef LV_LL_H +#define LV_LL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_mem.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Dummy type to make handling easier*/ +typedef uint8_t lv_ll_node_t; + +/*Description of a linked list*/ +typedef struct { + uint32_t n_size; + lv_ll_node_t *head; + lv_ll_node_t *tail; +} lv_ll_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize linked list + * @param ll_dsc pointer to ll_dsc variable + * @param node_size the size of 1 node in bytes + */ +void lv_ll_init(lv_ll_t *ll_p, uint32_t node_size); + +/** + * Add a new head to a linked list + * @param ll_p pointer to linked list + * @return pointer to the new head + */ +void *lv_ll_ins_head(lv_ll_t *ll_p); + +/** + * Insert a new node in front of the n_act node + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the new head + */ +void *lv_ll_ins_prev(lv_ll_t *ll_p, void *n_act); + +/** + * Add a new tail to a linked list + * @param ll_p pointer to linked list + * @return pointer to the new tail + */ +void *lv_ll_ins_tail(lv_ll_t *ll_p); + +/** + * Remove the node 'node_p' from 'll_p' linked list. + * It Dose not free the the memory of node. + * @param ll_p pointer to the linked list of 'node_p' + * @param node_p pointer to node in 'll_p' linked list + */ +void lv_ll_rem(lv_ll_t *ll_p, void *node_p); + +/** + * Remove and free all elements from a linked list. The list remain valid but + * become empty. + * @param ll_p pointer to linked list + */ +void lv_ll_clear(lv_ll_t *ll_p); + +/** + * Move a node to a new linked list + * @param ll_ori_p pointer to the original (old) linked list + * @param ll_new_p pointer to the new linked list + * @param node pointer to a node + */ +void lv_ll_chg_list(lv_ll_t *ll_ori_p, lv_ll_t *ll_new_p, void *node); + +/** + * Return with head node of the linked list + * @param ll_p pointer to linked list + * @return pointer to the head of 'll_p' + */ +void *lv_ll_get_head(lv_ll_t *ll_p); + +/** + * Return with tail node of the linked list + * @param ll_p pointer to linked list + * @return pointer to the head of 'll_p' + */ +void *lv_ll_get_tail(lv_ll_t *ll_p); + +/** + * Return with the pointer of the next node after 'n_act' + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the next node + */ +void *lv_ll_get_next(lv_ll_t *ll_p, void *n_act); + +/** + * Return with the pointer of the previous node after 'n_act' + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the previous node + */ +void *lv_ll_get_prev(lv_ll_t *ll_p, void *n_act); + +/********************** + * MACROS + **********************/ + +#define LL_READ(list, i) \ + for (i = lv_ll_get_head(&list); i != NULL; i = lv_ll_get_next(&list, i)) + +#define LL_READ_BACK(list, i) \ + for (i = lv_ll_get_tail(&list); i != NULL; i = lv_ll_get_prev(&list, i)) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_math.h b/include/display/lv_misc/lv_math.h new file mode 100644 index 0000000..a5a5a74 --- /dev/null +++ b/include/display/lv_misc/lv_math.h @@ -0,0 +1,50 @@ +/** + * @file math_base.h + * + */ + +#ifndef LV_MATH_H +#define LV_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ + +#define LV_MATH_MIN(a, b) (a < b ? a : b) +#define LV_MATH_MAX(a, b) (a > b ? a : b) +#define LV_MATH_ABS(x) ((x) > 0 ? (x) : (-(x))) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +/** + * Convert a number to string + * @param num a number + * @param buf pointer to a `char` buffer. The result will be stored here (max 10 + * elements) + * @return same as `buf` (just for convenience) + */ +char *lv_math_num_to_str(int32_t num, char *buf); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_mem.h b/include/display/lv_misc/lv_mem.h new file mode 100644 index 0000000..0574591 --- /dev/null +++ b/include/display/lv_misc/lv_mem.h @@ -0,0 +1,106 @@ +/** + * @file lv_mem.h + * + */ + +#ifndef LV_MEM_H +#define LV_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint32_t total_size; + uint32_t free_cnt; + uint32_t free_size; + uint32_t free_biggest_size; + uint32_t used_cnt; + uint8_t used_pct; + uint8_t frag_pct; +} lv_mem_monitor_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initiaize the dyn_mem module (work memory and other variables) + */ +void lv_mem_init(void); + +/** + * Allocate a memory dynamically + * @param size size of the memory to allocate in bytes + * @return pointer to the allocated memory + */ +void *lv_mem_alloc(uint32_t size); + +/** + * Free an allocated data + * @param data pointer to an allocated memory + */ +void lv_mem_free(const void *data); + +/** + * Reallocate a memory with a new size. The old content will be kept. + * @param data pointer to an allocated memory. + * Its content will be copied to the new memory block and freed + * @param new_size the desired new size in byte + * @return pointer to the new memory + */ +void *lv_mem_realloc(void *data_p, uint32_t new_size); + +/** + * Join the adjacent free memory blocks + */ +void lv_mem_defrag(void); + +/** + * Give information about the work memory of dynamic allocation + * @param mon_p pointer to a dm_mon_p variable, + * the result of the analysis will be stored here + */ +void lv_mem_monitor(lv_mem_monitor_t *mon_p); + +/** + * Give the size of an allocated memory + * @param data pointer to an allocated memory + * @return the size of data memory in bytes + */ +uint32_t lv_mem_get_size(const void *data); + +/** + * Halt o NULL pointer + * p pointer to a memory + */ +static inline void lv_mem_assert(void *p) { + if (p == NULL) { + while (1) + ; + } +} + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_MEM_H*/ diff --git a/include/display/lv_misc/lv_misc.mk b/include/display/lv_misc/lv_misc.mk new file mode 100644 index 0000000..9ffbb14 --- /dev/null +++ b/include/display/lv_misc/lv_misc.mk @@ -0,0 +1,18 @@ +CSRCS += lv_font.c +CSRCS += lv_circ.c +CSRCS += lv_area.c +CSRCS += lv_task.c +CSRCS += lv_fs.c +CSRCS += lv_anim.c +CSRCS += lv_mem.c +CSRCS += lv_ll.c +CSRCS += lv_color.c +CSRCS += lv_txt.c +CSRCS += lv_ufs.c +CSRCS += lv_trigo.c +CSRCS += lv_math.c + +DEPPATH += --dep-path lvgl/lv_misc +VPATH += :lvgl/lv_misc + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_misc" diff --git a/include/display/lv_misc/lv_task.h b/include/display/lv_misc/lv_task.h new file mode 100644 index 0000000..78c00e7 --- /dev/null +++ b/include/display/lv_misc/lv_task.h @@ -0,0 +1,142 @@ +/** + * @file lv_task.c + * An 'lv_task' is a void (*fp) (void* param) type function which will be + * called periodically. + * A priority (5 levels + disable) can be assigned to lv_tasks. + */ + +#ifndef LV_TASK_H +#define LV_TASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_ll.h" +#include "lv_mem.h" +#include +#include + +/********************* + * DEFINES + *********************/ +#ifndef LV_ATTRIBUTE_TASK_HANDLER +#define LV_ATTRIBUTE_TASK_HANDLER +#endif +/********************** + * TYPEDEFS + **********************/ +/** + * Possible priorities for lv_tasks + */ +typedef enum { + LV_TASK_PRIO_OFF = 0, + LV_TASK_PRIO_LOWEST, + LV_TASK_PRIO_LOW, + LV_TASK_PRIO_MID, + LV_TASK_PRIO_HIGH, + LV_TASK_PRIO_HIGHEST, + LV_TASK_PRIO_NUM, +} lv_task_prio_t; + +/** + * Descriptor of a lv_task + */ +typedef struct { + uint32_t period; + uint32_t last_run; + void (*task)(void *); + void *param; + uint8_t prio : 3; + uint8_t once : 1; +} lv_task_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init the lv_task module + */ +void lv_task_init(void); + +/** + * Call it periodically to handle lv_tasks. + */ +LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void); + +/** + * Create a new lv_task + * @param task a function which is the task itself + * @param period call period in ms unit + * @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped) + * @param param free parameter + * @return pointer to the new task + */ +lv_task_t *lv_task_create(void (*task)(void *), uint32_t period, + lv_task_prio_t prio, void *param); + +/** + * Delete a lv_task + * @param lv_task_p pointer to task created by lv_task_p + */ +void lv_task_del(lv_task_t *lv_task_p); + +/** + * Set new priority for a lv_task + * @param lv_task_p pointer to a lv_task + * @param prio the new priority + */ +void lv_task_set_prio(lv_task_t *lv_task_p, lv_task_prio_t prio); + +/** + * Set new period for a lv_task + * @param lv_task_p pointer to a lv_task + * @param period the new period + */ +void lv_task_set_period(lv_task_t *lv_task_p, uint32_t period); + +/** + * Make a lv_task ready. It will not wait its period. + * @param lv_task_p pointer to a lv_task. + */ +void lv_task_ready(lv_task_t *lv_task_p); + +/** + * Delete the lv_task after one call + * @param lv_task_p pointer to a lv_task. + */ +void lv_task_once(lv_task_t *lv_task_p); + +/** + * Reset a lv_task. + * It will be called the previously set period milliseconds later. + * @param lv_task_p pointer to a lv_task. + */ +void lv_task_reset(lv_task_t *lv_task_p); + +/** + * Enable or disable the whole lv_task handling + * @param en: true: lv_task handling is running, false: lv_task handling is + * suspended + */ +void lv_task_enable(bool en); + +/** + * Get idle percentage + * @return the lv_task idle in percentage + */ +uint8_t lv_task_get_idle(void); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_templ.h b/include/display/lv_misc/lv_templ.h new file mode 100644 index 0000000..fad8693 --- /dev/null +++ b/include/display/lv_misc/lv_templ.h @@ -0,0 +1,42 @@ +/** + * @file lv_templ.h + * + */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + +#ifndef LV_TEMPL_H +#define LV_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TEMPL_H*/ + +#pragma GCC diagnostic pop diff --git a/include/display/lv_misc/lv_trigo.h b/include/display/lv_misc/lv_trigo.h new file mode 100644 index 0000000..cba8a53 --- /dev/null +++ b/include/display/lv_misc/lv_trigo.h @@ -0,0 +1,47 @@ +/** + * @file lv_trig.h + * Basic trigonometric integer functions + */ + +#ifndef LV_TRIGO_H +#define LV_TRIGO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ +#define LV_TRIGO_SIN_MAX 32767 +#define LV_TRIGO_SHIFT 15 /* >> LV_TRIGO_SHIFT to normalize*/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Return with sinus of an angle + * @param angle + * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 + */ +int16_t lv_trigo_sin(int16_t angle); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_misc/lv_txt.h b/include/display/lv_misc/lv_txt.h new file mode 100644 index 0000000..3bb4896 --- /dev/null +++ b/include/display/lv_misc/lv_txt.h @@ -0,0 +1,178 @@ +/** + * @file lv_text.h + * + */ + +#ifndef LV_TXT_H +#define LV_TXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "lv_area.h" +#include "lv_font.h" +#include "lv_area.h" + +/********************* + * DEFINES + *********************/ +#define LV_TXT_COLOR_CMD "#" + +/********************** + * TYPEDEFS + **********************/ +typedef enum +{ + LV_TXT_FLAG_NONE = 0x00, + LV_TXT_FLAG_RECOLOR = 0x01, /*Enable parsing of recolor command*/ + LV_TXT_FLAG_EXPAND = 0x02, /*Ignore width (Used by the library)*/ + LV_TXT_FLAG_NO_BREAK = 0x04, /*Ignore line breaks (Used by the library)*/ + LV_TXT_FLAG_CENTER = 0x08, /*Align the text to the middle*/ +}lv_txt_flag_t; + +typedef enum +{ + LV_TXT_CMD_STATE_WAIT, /*Waiting for command*/ + LV_TXT_CMD_STATE_PAR, /*Processing the parameter*/ + LV_TXT_CMD_STATE_IN, /*Processing the command*/ +}lv_txt_cmd_state_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Get size of a text + * @param size_res pointer to a 'point_t' variable to store the result + * @param text pointer to a text + * @param font pinter to font of the text + * @param letter_space letter space of the text + * @param line_space line space of the text + * @param flags settings for the text from 'txt_flag_t' enum + * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks + */ +void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, + lv_coord_t letter_space, lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag); + +/** + * Get the next line of text. Check line length and break chars too. + * @param txt a '\0' terminated string + * @param font_p pointer to a font + * @param letter_space letter space + * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks + * @param flags settings for the text from 'txt_flag_t' enum + * @return the index of the first char of the new line + */ +uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font_p, + lv_coord_t letter_space, lv_coord_t max_l, lv_txt_flag_t flag); + +/** + * Give the length of a text with a given font + * @param txt a '\0' terminate string + * @param char_num number of characters in 'txt' + * @param font_p pointer to a font + * @param letter_space letter space + * @param flags settings for the text from 'txt_flag_t' enum + * @return length of a char_num long text + */ +lv_coord_t lv_txt_get_width(const char * txt, uint16_t char_num, + const lv_font_t * font_p, lv_coord_t letter_space, lv_txt_flag_t flag); + +/** + * Check next character in a string and decide if te character is part of the command or not + * @param state pointer to a txt_cmd_state_t variable which stores the current state of command processing + * @param c the current character + * @return true: the character is part of a command and should not be written, + * false: the character should be written + */ +bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c); + +/** + * Insert a string into an other + * @param txt_buf the original text (must be big enough for the result text) + * @param pos position to insert (0: before the original text, 1: after the first char etc.) + * @param ins_txt text to insert + */ +void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); + +/** + * Delete a part of a string + * @param txt string to modify + * @param pos position where to start the deleting (0: before the first char, 1: after the first char etc.) + * @param len number of characters to delete + */ +void lv_txt_cut(char * txt, uint32_t pos, uint32_t len); + +/** + * Give the size of an UTF-8 coded character + * @param c A character where the UTF-8 character starts + * @return length of the UTF-8 character (1,2,3 or 4). O on invalid code + */ +uint8_t lv_txt_utf8_size(uint8_t c); + + +/** + * Convert an Unicode letter to UTF-8. + * @param letter_uni an Unicode letter + * @return UTF-8 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű') + */ +uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni); + +/** + * Decode an UTF-8 character from a string. + * @param txt pointer to '\0' terminated string + * @param i start index in 'txt' where to start. + * After the call it will point to the next UTF-8 char in 'txt'. + * NULL to use txt[0] as index + * @return the decoded Unicode character or 0 on invalid UTF-8 code + */ +uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i); + +/** + * Get previous UTF-8 character form a string. + * @param txt pointer to '\0' terminated string + * @param i_start index in 'txt' where to start. After the call it will point to the next UTF-8 char in 'txt'. + * @return the decoded Unicode character or 0 on invalid UTF-8 code + */ +uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start); + +/** + * Convert a letter index (in an UTF-8 text) to byte index. + * E.g. in "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long + * @param txt a '\0' terminated UTF-8 string + * @param utf8_id letter index + * @return byte index of the 'utf8_id'th letter + */ +uint32_t txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id); + +/** + * Convert a byte index (in an UTF-8 text) to character index. + * E.g. in "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long + * @param txt a '\0' terminated UTF-8 string + * @param byte_id byte index + * @return character index of the letter at 'byte_id'th position + */ +uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id); + +/** + * Get the number of characters (and NOT bytes) in a string. Decode it with UTF-8 if enabled. + * E.g.: "ÁBC" is 3 characters (but 4 bytes) + * @param txt a '\0' terminated char string + * @return number of characters + */ +uint32_t lv_txt_get_length(const char * txt); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*USE_TXT*/ diff --git a/include/display/lv_misc/lv_ufs.h b/include/display/lv_misc/lv_ufs.h new file mode 100644 index 0000000..bc94d72 --- /dev/null +++ b/include/display/lv_misc/lv_ufs.h @@ -0,0 +1,208 @@ +/** + * @file lv_ufs.h + * Implementation of RAM file system which do NOT support directories. + * The API is compatible with the lv_fs_int module. + */ + +#ifndef LV_UFS_H +#define LV_UFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if USE_LV_FILESYSTEM + +#include "lv_fs.h" +#include "lv_mem.h" +#include + +/********************* + * DEFINES + *********************/ +#define UFS_LETTER 'U' + +/********************** + * TYPEDEFS + **********************/ +/*Description of a file entry */ +typedef struct { + char *fn_d; + void *data_d; + uint32_t size; /*Data length in bytes*/ + uint16_t oc; /*Open Count*/ + uint8_t const_data : 1; +} lv_ufs_ent_t; + +/*File descriptor, used to handle opening an entry more times simultaneously + Contains unique information about the specific opening*/ +typedef struct { + lv_ufs_ent_t *ent; /*Pointer to the entry*/ + uint32_t rwp; /*Read Write Pointer*/ + uint8_t ar : 1; /*1: Access for read is enabled */ + uint8_t aw : 1; /*1: Access for write is enabled */ +} lv_ufs_file_t; + +/* Read directory descriptor. + * It is used to to iterate through the entries in a directory*/ +typedef struct { lv_ufs_ent_t *last_ent; } lv_ufs_dir_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a driver for ufs and initialize it. + */ +void lv_ufs_init(void); + +/** + * Give the state of the ufs + * @return true if ufs is initialized and can be used else false + */ +bool lv_ufs_ready(void); + +/** + * Open a file in ufs + * @param file_p pointer to a lv_ufs_file_t variable + * @param fn name of the file. There are no directories so e.g. "myfile.txt" + * @param mode element of 'fs_mode_t' enum or its 'OR' connection (e.g. + * FS_MODE_WR | FS_MODE_RD) + * @return LV_FS_RES_OK: no error, the file is opened + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_open(void *file_p, const char *fn, lv_fs_mode_t mode); + +/** + * Create a file with a constant data + * @param fn name of the file (directories are not supported) + * @param const_p pointer to a constant data + * @param len length of the data pointed by 'const_p' in bytes + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_create_const(const char *fn, const void *const_p, + uint32_t len); + +/** + * Close an opened file + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_close(void *file_p); + +/** + * Remove a file. The file can not be opened. + * @param fn '\0' terminated string + * @return LV_FS_RES_OK: no error, the file is removed + * LV_FS_RES_DENIED: the file was opened, remove failed + */ +lv_fs_res_t lv_ufs_remove(const char *fn); + +/** + * Read data from an opened file + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open ) + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_read(void *file_p, void *buf, uint32_t btr, uint32_t *br); + +/** + * Write data to an opened file + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open) + * @param buf pointer to a memory block which content will be written + * @param btw the number Bytes To Write + * @param bw The real number of written bytes (Byte Written) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_write(void *file_p, const void *buf, uint32_t btw, + uint32_t *bw); + +/** + * Set the read write pointer. Also expand the file size if necessary. + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open ) + * @param pos the new position of read write pointer + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_seek(void *file_p, uint32_t pos); + +/** + * Give the position of the read write pointer + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open ) + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_tell(void *file_p, uint32_t *pos_p); + +/** + * Truncate the file size to the current position of the read write pointer + * @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_ufs_open ) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_trunc(void *file_p); + +/** + * Give the size of the file in bytes + * @param file_p file_p pointer to an 'ufs_file_t' variable. (opened with + * lv_ufs_open ) + * @param size_p pointer to store the size + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_size(void *file_p, uint32_t *size_p); + +/** + * Initialize a lv_ufs_read_dir_t variable to directory reading + * @param rddir_p pointer to a 'ufs_read_dir_t' variable + * @param path uFS doesn't support folders so it has to be "" + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_dir_open(void *rddir_p, const char *path); + +/** + * Read the next file name + * @param dir_p pointer to an initialized 'ufs_read_dir_t' variable + * @param fn pointer to buffer to sore the file name + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_dir_read(void *dir_p, char *fn); + +/** + * Close the directory reading + * @param rddir_p pointer to an initialized 'ufs_read_dir_t' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_ufs_dir_close(void *rddir_p); + +/** + * Give the size of a drive + * @param total_p pointer to store the total size [kB] + * @param free_p pointer to store the free site [kB] + * @return LV_FS_RES_OK or any error from 'fs_res_t' + */ +lv_fs_res_t lv_ufs_free(uint32_t *total_p, uint32_t *free_p); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_FILESYSTEM*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/display/lv_objx/lv_bar.h b/include/display/lv_objx/lv_bar.h new file mode 100644 index 0000000..917c6e3 --- /dev/null +++ b/include/display/lv_objx/lv_bar.h @@ -0,0 +1,138 @@ +/** + * @file lv_bar.h + * + */ + +#ifndef LV_BAR_H +#define LV_BAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_BAR != 0 + +#include "display/lv_core/lv_obj.h" +#include "lv_btn.h" +#include "lv_cont.h" +#include "lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of bar*/ +typedef struct { + /*No inherited ext*/ /*Ext. of ancestor*/ + /*New data for this type */ + int16_t cur_value; /*Current value of the bar*/ + int16_t min_value; /*Minimum value of the bar*/ + int16_t max_value; /*Maximum value of the bar*/ + lv_style_t *style_indic; /*Style of the indicator*/ +} lv_bar_ext_t; + +typedef enum { + LV_BAR_STYLE_BG, + LV_BAR_STYLE_INDIC, +} lv_bar_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a bar objects + * @param par pointer to an object, it will be the parent of the new bar + * @param copy pointer to a bar object, if not NULL then the new object will be + * copied from it + * @return pointer to the created bar + */ +lv_obj_t *lv_bar_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the bar + * @param bar pointer to a bar object + * @param value new value + */ +void lv_bar_set_value(lv_obj_t *bar, int16_t value); + +/** + * Set a new value with animation on the bar + * @param bar pointer to a bar object + * @param value new value + * @param anim_time animation time in milliseconds + */ +void lv_bar_set_value_anim(lv_obj_t *bar, int16_t value, uint16_t anim_time); + +/** + * Set minimum and the maximum values of a bar + * @param bar pointer to the bar object + * @param min minimum value + * @param max maximum value + */ +void lv_bar_set_range(lv_obj_t *bar, int16_t min, int16_t max); + +/** + * Set a style of a bar + * @param bar pointer to a bar object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_bar_set_style(lv_obj_t *bar, lv_bar_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a bar + * @param bar pointer to a bar object + * @return the value of the bar + */ +int16_t lv_bar_get_value(lv_obj_t *bar); + +/** + * Get the minimum value of a bar + * @param bar pointer to a bar object + * @return the minimum value of the bar + */ +int16_t lv_bar_get_min_value(lv_obj_t *bar); + +/** + * Get the maximum value of a bar + * @param bar pointer to a bar object + * @return the maximum value of the bar + */ +int16_t lv_bar_get_max_value(lv_obj_t *bar); + +/** + * Get a style of a bar + * @param bar pointer to a bar object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_bar_get_style(lv_obj_t *bar, lv_bar_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_BAR*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BAR_H*/ diff --git a/include/display/lv_objx/lv_btn.h b/include/display/lv_objx/lv_btn.h new file mode 100644 index 0000000..c59bca5 --- /dev/null +++ b/include/display/lv_objx/lv_btn.h @@ -0,0 +1,222 @@ +/** + * @file lv_btn.h + * + */ + +#ifndef LV_BTN_H +#define LV_BTN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_BTN != 0 + +/*Testing of dependencies*/ +#if USE_LV_CONT == 0 +#error "lv_btn: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) " +#endif + +#include "display/lv_core/lv_indev.h" +#include "display/lv_objx/lv_cont.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Button states*/ +typedef enum { + LV_BTN_STATE_REL, + LV_BTN_STATE_PR, + LV_BTN_STATE_TGL_REL, + LV_BTN_STATE_TGL_PR, + LV_BTN_STATE_INA, + LV_BTN_STATE_NUM, +} lv_btn_state_t; + +typedef enum { + LV_BTN_ACTION_CLICK, + LV_BTN_ACTION_PR, + LV_BTN_ACTION_LONG_PR, + LV_BTN_ACTION_LONG_PR_REPEAT, + LV_BTN_ACTION_NUM, +} lv_btn_action_t; + +/*Data of button*/ +typedef struct { + lv_cont_ext_t cont; /*Ext. of ancestor*/ + /*New data for this type */ + lv_action_t actions[LV_BTN_ACTION_NUM]; + lv_style_t *styles[LV_BTN_STATE_NUM]; /*Styles in each state*/ + + lv_btn_state_t + state; /*Current state of the button from 'lv_btn_state_t' enum*/ + uint8_t toggle : 1; /*1: Toggle enabled*/ + uint8_t + long_pr_action_executed : 1; /*1: Long press action executed (Handled by + the library)*/ +} lv_btn_ext_t; + +/*Styles*/ +typedef enum { + LV_BTN_STYLE_REL, + LV_BTN_STYLE_PR, + LV_BTN_STYLE_TGL_REL, + LV_BTN_STYLE_TGL_PR, + LV_BTN_STYLE_INA, +} lv_btn_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a button objects + * @param par pointer to an object, it will be the parent of the new button + * @param copy pointer to a button object, if not NULL then the new object will + * be copied from it + * @return pointer to the created button + */ +lv_obj_t *lv_btn_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Enable the toggled states. On release the button will change from/to toggled + * state. + * @param btn pointer to a button object + * @param tgl true: enable toggled states, false: disable + */ +void lv_btn_set_toggle(lv_obj_t *btn, bool tgl); + +/** + * Set the state of the button + * @param btn pointer to a button object + * @param state the new state of the button (from lv_btn_state_t enum) + */ +void lv_btn_set_state(lv_obj_t *btn, lv_btn_state_t state); + +/** + * Toggle the state of the button (ON->OFF, OFF->ON) + * @param btn pointer to a button object + */ +void lv_btn_toggle(lv_obj_t *btn); + +/** + * Set a function to call when the button event happens + * @param btn pointer to a button object + * @param action type of event form 'lv_action_t' (press, release, long press, + * long press repeat) + */ +void lv_btn_set_action(lv_obj_t *btn, lv_btn_action_t type, lv_action_t action); + +/** + * Set the layout on a button + * @param btn pointer to a button object + * @param layout a layout from 'lv_cont_layout_t' + */ +static inline void lv_btn_set_layout(lv_obj_t *btn, lv_layout_t layout) { + lv_cont_set_layout(btn, layout); +} + +/** + * Enable the horizontal or vertical fit. + * The button size will be set to involve the children horizontally or + * vertically. + * @param btn pointer to a button object + * @param hor_en true: enable the horizontal fit + * @param ver_en true: enable the vertical fit + */ +static inline void lv_btn_set_fit(lv_obj_t *btn, bool hor_en, bool ver_en) { + lv_cont_set_fit(btn, hor_en, ver_en); +} + +/** + * Set a style of a button. + * @param btn pointer to button object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_btn_set_style(lv_obj_t *btn, lv_btn_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the current state of the button + * @param btn pointer to a button object + * @return the state of the button (from lv_btn_state_t enum) + */ +lv_btn_state_t lv_btn_get_state(lv_obj_t *btn); + +/** + * Get the toggle enable attribute of the button + * @param btn pointer to a button object + * @return ture: toggle enabled, false: disabled + */ +bool lv_btn_get_toggle(lv_obj_t *btn); + +/** + * Get the release action of a button + * @param btn pointer to a button object + * @return pointer to the release action function + */ +lv_action_t lv_btn_get_action(lv_obj_t *btn, lv_btn_action_t type); + +/** + * Get the layout of a button + * @param btn pointer to button object + * @return the layout from 'lv_cont_layout_t' + */ +static inline lv_layout_t lv_btn_get_layout(lv_obj_t *btn) { + return lv_cont_get_layout(btn); +} + +/** + * Get horizontal fit enable attribute of a button + * @param btn pointer to a button object + * @return true: horizontal fit is enabled; false: disabled + */ +static inline bool lv_btn_get_hor_fit(lv_obj_t *btn) { + return lv_cont_get_hor_fit(btn); +} + +/** + * Get vertical fit enable attribute of a container + * @param btn pointer to a button object + * @return true: vertical fit is enabled; false: disabled + */ +static inline bool lv_btn_get_ver_fit(lv_obj_t *btn) { + return lv_cont_get_ver_fit(btn); +} + +/** + * Get style of a button. + * @param btn pointer to button object + * @param type which style should be get + * @return style pointer to the style + * */ +lv_style_t *lv_btn_get_style(lv_obj_t *btn, lv_btn_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_BUTTON*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BTN_H*/ diff --git a/include/display/lv_objx/lv_btnm.h b/include/display/lv_objx/lv_btnm.h new file mode 100644 index 0000000..2d34e29 --- /dev/null +++ b/include/display/lv_objx/lv_btnm.h @@ -0,0 +1,174 @@ +/** + * @file lv_btnm.h + * + */ + +#ifndef LV_BTNM_H +#define LV_BTNM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_BTNM != 0 + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btn.h" +#include "display/lv_objx/lv_label.h" + +/********************* + * DEFINES + *********************/ + +/*Control byte*/ +#define LV_BTNM_CTRL_CODE \ + 0x80 /*The control byte has to begin (if present) with 0b10xxxxxx*/ +#define LV_BTNM_CTRL_MASK 0xC0 +#define LV_BTNM_WIDTH_MASK 0x07 +#define LV_BTNM_HIDE_MASK 0x08 +#define LV_BTNM_REPEAT_DISABLE_MASK 0x10 +#define LV_BTNM_INACTIVE_MASK 0x20 + +/********************** + * TYPEDEFS + **********************/ + +/* Type of callback function which is called when a button is released or long + * pressed on the button matrix + * Parameters: button matrix, text of the released button + * return LV_ACTION_RES_INV if the button matrix is deleted else + * LV_ACTION_RES_OK*/ +typedef lv_res_t (*lv_btnm_action_t)(lv_obj_t *, const char *txt); + +/*Data of button matrix*/ +typedef struct { + /*No inherited ext.*/ /*Ext. of ancestor*/ + /*New data for this type */ + const char **map_p; /*Pointer to the current map*/ + lv_area_t *button_areas; /*Array of areas of buttons*/ + lv_btnm_action_t action; /*A function to call when a button is releases*/ + lv_style_t *styles_btn[LV_BTN_STATE_NUM]; /*Styles of buttons in each state*/ + uint16_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/ + uint16_t btn_id_pr; /*Index of the currently pressed button (in + `button_areas`) or LV_BTNM_PR_NONE*/ + uint16_t btn_id_tgl; /*Index of the currently toggled button (in + `button_areas`) or LV_BTNM_PR_NONE */ + uint8_t toggle : 1; /*Enable toggling*/ +} lv_btnm_ext_t; + +typedef enum { + LV_BTNM_STYLE_BG, + LV_BTNM_STYLE_BTN_REL, + LV_BTNM_STYLE_BTN_PR, + LV_BTNM_STYLE_BTN_TGL_REL, + LV_BTNM_STYLE_BTN_TGL_PR, + LV_BTNM_STYLE_BTN_INA, +} lv_btnm_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a button matrix objects + * @param par pointer to an object, it will be the parent of the new button + * matrix + * @param copy pointer to a button matrix object, if not NULL then the new + * object will be copied from it + * @return pointer to the created button matrix + */ +lv_obj_t *lv_btnm_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new map. Buttons will be created/deleted according to the map. + * @param btnm pointer to a button matrix object + * @param map pointer a string array. The last string has to be: "". + * Use "\n" to begin a new line. + * The first byte can be a control data: + * - bit 7: always 1 + * - bit 6: always 0 + * - bit 5: inactive (disabled) + * - bit 4: no repeat (on long press) + * - bit 3: hidden + * - bit 2..0: button relative width + * Example (practically use octal numbers): "\224abc": "abc" text + * with 4 width and no long press + */ +void lv_btnm_set_map(lv_obj_t *btnm, const char **map); + +/** + * Set a new callback function for the buttons (It will be called when a button + * is released) + * @param btnm: pointer to button matrix object + * @param action pointer to a callback function + */ +void lv_btnm_set_action(lv_obj_t *btnm, lv_btnm_action_t action); + +/** + * Enable or disable button toggling + * @param btnm pointer to button matrix object + * @param en true: enable toggling; false: disable toggling + * @param id index of the currently toggled button (ignored if 'en' == false) + */ +void lv_btnm_set_toggle(lv_obj_t *btnm, bool en, uint16_t id); + +/** + * Set a style of a button matrix + * @param btnm pointer to a button matrix object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_btnm_set_style(lv_obj_t *btnm, lv_btnm_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the current map of a button matrix + * @param btnm pointer to a button matrix object + * @return the current map + */ +const char **lv_btnm_get_map(lv_obj_t *btnm); + +/** + * Get a the callback function of the buttons on a button matrix + * @param btnm: pointer to button matrix object + * @return pointer to the callback function + */ +lv_btnm_action_t lv_btnm_get_action(lv_obj_t *btnm); + +/** + * Get the toggled button + * @param btnm pointer to button matrix object + * @return index of the currently toggled button (0: if unset) + */ +uint16_t lv_btnm_get_toggled(lv_obj_t *btnm); + +/** + * Get a style of a button matrix + * @param btnm pointer to a button matrix object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_btnm_get_style(lv_obj_t *btnm, lv_btnm_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_BTNM*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BTNM_H*/ diff --git a/include/display/lv_objx/lv_cb.h b/include/display/lv_objx/lv_cb.h new file mode 100644 index 0000000..adf2eb4 --- /dev/null +++ b/include/display/lv_objx/lv_cb.h @@ -0,0 +1,161 @@ +/** + * @file lv_cb.h + * + */ + +#ifndef LV_CB_H +#define LV_CB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_CB != 0 + +/*Testing of dependencies*/ +#if USE_LV_BTN == 0 +#error "lv_cb: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) " +#endif + +#if USE_LV_LABEL == 0 +#error "lv_cb: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btn.h" +#include "display/lv_objx/lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of check box*/ +typedef struct { + lv_btn_ext_t bg_btn; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *bullet; /*Pointer to button*/ + lv_obj_t *label; /*Pointer to label*/ +} lv_cb_ext_t; + +typedef enum { + LV_CB_STYLE_BG, + LV_CB_STYLE_BOX_REL, + LV_CB_STYLE_BOX_PR, + LV_CB_STYLE_BOX_TGL_REL, + LV_CB_STYLE_BOX_TGL_PR, + LV_CB_STYLE_BOX_INA, +} lv_cb_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a check box objects + * @param par pointer to an object, it will be the parent of the new check box + * @param copy pointer to a check box object, if not NULL then the new object + * will be copied from it + * @return pointer to the created check box + */ +lv_obj_t *lv_cb_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the text of a check box + * @param cb pointer to a check box + * @param txt the text of the check box + */ +void lv_cb_set_text(lv_obj_t *cb, const char *txt); + +/** + * Set the state of the check box + * @param cb pointer to a check box object + * @param checked true: make the check box checked; false: make it unchecked + */ +static inline void lv_cb_set_checked(lv_obj_t *cb, bool checked) { + lv_btn_set_state(cb, checked ? LV_BTN_STATE_TGL_REL : LV_BTN_STATE_REL); +} + +/** + * Make the check box inactive (disabled) + * @param cb pointer to a check box object + */ +static inline void lv_cb_set_inactive(lv_obj_t *cb) { + lv_btn_set_state(cb, LV_BTN_STATE_INA); +} + +/** + * Set a function to call when the check box is clicked + * @param cb pointer to a check box object + */ +static inline void lv_cb_set_action(lv_obj_t *cb, lv_action_t action) { + lv_btn_set_action(cb, LV_BTN_ACTION_CLICK, action); +} + +/** + * Set a style of a check box + * @param cb pointer to check box object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_cb_set_style(lv_obj_t *cb, lv_cb_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a check box + * @param cb pointer to check box object + * @return pointer to the text of the check box + */ +const char *lv_cb_get_text(lv_obj_t *cb); + +/** + * Get the current state of the check box + * @param cb pointer to a check box object + * @return true: checked; false: not checked + */ +static inline bool lv_cb_is_checked(lv_obj_t *cb) { + return lv_btn_get_state(cb) == LV_BTN_STATE_REL ? false : true; +} + +/** + * Get the action of a check box + * @param cb pointer to a button object + * @return pointer to the action function + */ +static inline lv_action_t lv_cb_get_action(lv_obj_t *cb) { + return lv_btn_get_action(cb, LV_BTN_ACTION_CLICK); +} + +/** + * Get a style of a button + * @param cb pointer to check box object + * @param type which style should be get + * @return style pointer to the style + * */ +lv_style_t *lv_cb_get_style(lv_obj_t *cb, lv_cb_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_CB*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_CB_H*/ diff --git a/include/display/lv_objx/lv_chart.h b/include/display/lv_objx/lv_chart.h new file mode 100644 index 0000000..304a443 --- /dev/null +++ b/include/display/lv_objx/lv_chart.h @@ -0,0 +1,245 @@ +/** + * @file lv_chart.h + * + */ + +#ifndef LV_CHART_H +#define LV_CHART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_CHART != 0 + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_line.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_coord_t *points; + lv_color_t color; +} lv_chart_series_t; + +/*Data of chart */ +typedef struct { + /*No inherited ext*/ /*Ext. of ancestor*/ + /*New data for this type */ + lv_ll_t series_ll; /*Linked list for the data line pointers (stores + lv_chart_dl_t)*/ + lv_coord_t ymin; /*y min value (used to scale the data)*/ + lv_coord_t ymax; /*y max value (used to scale the data)*/ + uint8_t hdiv_cnt; /*Number of horizontal division lines*/ + uint8_t vdiv_cnt; /*Number of vertical division lines*/ + uint16_t point_cnt; /*Point number in a data line*/ + uint8_t type : 3; /*Line, column or point chart (from 'lv_chart_type_t')*/ + struct { + lv_coord_t width; /*Line width or point radius*/ + uint8_t num; /*Number of data lines in dl_ll*/ + lv_opa_t opa; /*Opacity of data lines*/ + lv_opa_t dark; /*Dark level of the point/column bottoms*/ + } series; +} lv_chart_ext_t; + +/*Chart types*/ +typedef enum { + LV_CHART_TYPE_LINE = 0x01, + LV_CHART_TYPE_COLUMN = 0x02, + LV_CHART_TYPE_POINT = 0x04, +} lv_chart_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a chart background objects + * @param par pointer to an object, it will be the parent of the new chart + * background + * @param copy pointer to a chart background object, if not NULL then the new + * object will be copied from it + * @return pointer to the created chart background + */ +lv_obj_t *lv_chart_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Allocate and add a data series to the chart + * @param chart pointer to a chart object + * @param color color of the data series + * @return pointer to the allocated data series + */ +lv_chart_series_t *lv_chart_add_series(lv_obj_t *chart, lv_color_t color); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the number of horizontal and vertical division lines + * @param chart pointer to a graph background object + * @param hdiv number of horizontal division lines + * @param vdiv number of vertical division lines + */ +void lv_chart_set_div_line_count(lv_obj_t *chart, uint8_t hdiv, uint8_t vdiv); + +/** + * Set the minimal and maximal y values + * @param chart pointer to a graph background object + * @param ymin y minimum value + * @param ymax y maximum value + */ +void lv_chart_set_range(lv_obj_t *chart, lv_coord_t ymin, lv_coord_t ymax); + +/** + * Set a new type for a chart + * @param chart pointer to a chart object + * @param type new type of the chart (from 'lv_chart_type_t' enum) + */ +void lv_chart_set_type(lv_obj_t *chart, lv_chart_type_t type); + +/** + * Set the number of points on a data line on a chart + * @param chart pointer r to chart object + * @param point_cnt new number of points on the data lines + */ +void lv_chart_set_point_count(lv_obj_t *chart, uint16_t point_cnt); + +/** + * Set the opacity of the data series + * @param chart pointer to a chart object + * @param opa opacity of the data series + */ +void lv_chart_set_series_opa(lv_obj_t *chart, lv_opa_t opa); + +/** + * Set the line width or point radius of the data series + * @param chart pointer to a chart object + * @param width the new width + */ +void lv_chart_set_series_width(lv_obj_t *chart, lv_coord_t width); + +/** + * Set the dark effect on the bottom of the points or columns + * @param chart pointer to a chart object + * @param dark_eff dark effect level (LV_OPA_TRANSP to turn off) + */ +void lv_chart_set_series_darking(lv_obj_t *chart, lv_opa_t dark_eff); + +/** + * Initialize all data points with a value + * @param chart pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param y the new value for all points + */ +void lv_chart_init_points(lv_obj_t *chart, lv_chart_series_t *ser, + lv_coord_t y); + +/** + * Set the value s of points from an array + * @param chart pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param y_array array of 'lv_coord_t' points (with 'points count' elements ) + */ +void lv_chart_set_points(lv_obj_t *chart, lv_chart_series_t *ser, + lv_coord_t *y_array); + +/** + * Shift all data right and set the most right data on a data line + * @param chart pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param y the new value of the most right data + */ +void lv_chart_set_next(lv_obj_t *chart, lv_chart_series_t *ser, lv_coord_t y); + +/** + * Set the style of a chart + * @param chart pointer to a chart object + * @param style pointer to a style + */ +static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style) { + lv_obj_set_style(chart, style); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the type of a chart + * @param chart pointer to chart object + * @return type of the chart (from 'lv_chart_t' enum) + */ +lv_chart_type_t lv_chart_get_type(lv_obj_t *chart); + +/** + * Get the data point number per data line on chart + * @param chart pointer to chart object + * @return point number on each data line + */ +uint16_t lv_chart_get_point_cnt(lv_obj_t *chart); + +/** + * Get the opacity of the data series + * @param chart pointer to chart object + * @return the opacity of the data series + */ +lv_opa_t lv_chart_get_series_opa(lv_obj_t *chart); + +/** + * Get the data series width + * @param chart pointer to chart object + * @return the width the data series (lines or points) + */ +lv_coord_t lv_chart_get_series_width(lv_obj_t *chart); + +/** + * Get the dark effect level on the bottom of the points or columns + * @param chart pointer to chart object + * @return dark effect level (LV_OPA_TRANSP to turn off) + */ +lv_opa_t lv_chart_get_series_darking(lv_obj_t *chart); + +/** + * Get the style of an chart object + * @param chart pointer to an chart object + * @return pointer to the chart's style + */ +static inline lv_style_t *lv_chart_get_style(lv_obj_t *chart) { + return lv_obj_get_style(chart); +} + +/*===================== + * Other functions + *====================*/ + +/** + * Refresh a chart if its data line has changed + * @param chart pointer to chart object + */ +void lv_chart_refresh(lv_obj_t *chart); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_CHART*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_CHART_H*/ diff --git a/include/display/lv_objx/lv_cont.h b/include/display/lv_objx/lv_cont.h new file mode 100644 index 0000000..2203825 --- /dev/null +++ b/include/display/lv_objx/lv_cont.h @@ -0,0 +1,139 @@ +/** + * @file lv_cont.h + * + */ + +#ifndef LV_CONT_H +#define LV_CONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_CONT != 0 + +#include "display/lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Layout options*/ +typedef enum { + LV_LAYOUT_OFF = 0, + LV_LAYOUT_CENTER, + LV_LAYOUT_COL_L, /*Column left align*/ + LV_LAYOUT_COL_M, /*Column middle align*/ + LV_LAYOUT_COL_R, /*Column right align*/ + LV_LAYOUT_ROW_T, /*Row top align*/ + LV_LAYOUT_ROW_M, /*Row middle align*/ + LV_LAYOUT_ROW_B, /*Row bottom align*/ + LV_LAYOUT_PRETTY, /*Put as many object as possible in row and begin a new + row*/ + LV_LAYOUT_GRID, /*Align same-sized object into a grid*/ +} lv_layout_t; + +typedef struct { + /*Inherited from 'base_obj' so no inherited ext. */ /*Ext. of ancestor*/ + /*New data for this type */ + uint8_t layout : 4; /*A layout from 'lv_cont_layout_t' enum*/ + uint8_t hor_fit : 1; /*1: Enable horizontal fit to involve all children*/ + uint8_t ver_fit : 1; /*1: Enable horizontal fir to involve all children*/ +} lv_cont_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a container objects + * @param par pointer to an object, it will be the parent of the new container + * @param copy pointer to a container object, if not NULL then the new object + * will be copied from it + * @return pointer to the created container + */ +lv_obj_t *lv_cont_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a layout on a container + * @param cont pointer to a container object + * @param layout a layout from 'lv_cont_layout_t' + */ +void lv_cont_set_layout(lv_obj_t *cont, lv_layout_t layout); + +/** + * Enable the horizontal or vertical fit. + * The container size will be set to involve the children horizontally or + * vertically. + * @param cont pointer to a container object + * @param hor_en true: enable the horizontal fit + * @param ver_en true: enable the vertical fit + */ +void lv_cont_set_fit(lv_obj_t *cont, bool hor_en, bool ver_en); + +/** + * Set the style of a container + * @param cont pointer to a container object + * @param style pointer to the new style + */ +static inline void lv_cont_set_style(lv_obj_t *cont, lv_style_t *style) { + lv_obj_set_style(cont, style); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the layout of a container + * @param cont pointer to container object + * @return the layout from 'lv_cont_layout_t' + */ +lv_layout_t lv_cont_get_layout(lv_obj_t *cont); + +/** + * Get horizontal fit enable attribute of a container + * @param cont pointer to a container object + * @return true: horizontal fit is enabled; false: disabled + */ +bool lv_cont_get_hor_fit(lv_obj_t *cont); + +/** + * Get vertical fit enable attribute of a container + * @param cont pointer to a container object + * @return true: vertical fit is enabled; false: disabled + */ +bool lv_cont_get_ver_fit(lv_obj_t *cont); + +/** + * Get the style of a container + * @param cont pointer to a container object + * @return pointer to the container's style + */ +static inline lv_style_t *lv_cont_get_style(lv_obj_t *cont) { + return lv_obj_get_style(cont); +} + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_CONT*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_CONT_H*/ diff --git a/include/display/lv_objx/lv_ddlist.h b/include/display/lv_objx/lv_ddlist.h new file mode 100644 index 0000000..295bb90 --- /dev/null +++ b/include/display/lv_objx/lv_ddlist.h @@ -0,0 +1,232 @@ +/** + * @file lv_ddlist.h + * + */ + +#ifndef LV_DDLIST_H +#define LV_DDLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_DDLIST != 0 + +/*Testing of dependencies*/ +#if USE_LV_PAGE == 0 +#error \ + "lv_ddlist: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) " +#endif + +#if USE_LV_LABEL == 0 +#error \ + "lv_ddlist: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_label.h" +#include "display/lv_objx/lv_page.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of drop down list*/ +typedef struct { + lv_page_ext_t page; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *label; /*Label for the options*/ + lv_style_t *sel_style; /*Style of the selected option*/ + lv_action_t action; /*Pointer to function to call when an option is selected*/ + uint16_t option_cnt; /*Number of options*/ + uint16_t sel_opt_id; /*Index of the current option*/ + uint16_t sel_opt_id_ori; /*Store the original index on focus*/ + uint16_t anim_time; /*Open/Close animation time [ms]*/ + uint8_t opened : 1; /*1: The list is opened*/ + lv_coord_t fix_height; /*Height if the ddlist is opened. (0: auto-size)*/ +} lv_ddlist_ext_t; + +typedef enum { + LV_DDLIST_STYLE_BG, + LV_DDLIST_STYLE_SEL, + LV_DDLIST_STYLE_SB, +} lv_ddlist_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +/** + * Create a drop down list objects + * @param par pointer to an object, it will be the parent of the new drop down + * list + * @param copy pointer to a drop down list object, if not NULL then the new + * object will be copied from it + * @return pointer to the created drop down list + */ +lv_obj_t *lv_ddlist_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the options in a drop down list from a string + * @param ddlist pointer to drop down list object + * @param options a string with '\n' separated options. E.g. "One\nTwo\nThree" + */ +void lv_ddlist_set_options(lv_obj_t *ddlist, const char *options); + +/** + * Set the selected option + * @param ddlist pointer to drop down list object + * @param sel_opt id of the selected option (0 ... number of option - 1); + */ +void lv_ddlist_set_selected(lv_obj_t *ddlist, uint16_t sel_opt); + +/** + * Set a function to call when a new option is chosen + * @param ddlist pointer to a drop down list + * @param action pointer to a call back function + */ +void lv_ddlist_set_action(lv_obj_t *ddlist, lv_action_t action); + +/** + * Set the fix height for the drop down list + * If 0 then the opened ddlist will be auto. sized else the set height will be + * applied. + * @param ddlist pointer to a drop down list + * @param h the height when the list is opened (0: auto size) + */ +void lv_ddlist_set_fix_height(lv_obj_t *ddlist, lv_coord_t h); + +/** + * Enable or disable the horizontal fit to the content + * @param ddlist pointer to a drop down list + * @param fit en true: enable auto fit; false: disable auto fit + */ +void lv_ddlist_set_hor_fit(lv_obj_t *ddlist, bool fit_en); + +/** + * Set the scroll bar mode of a drop down list + * @param ddlist pointer to a drop down list object + * @param sb_mode the new mode from 'lv_page_sb_mode_t' enum + */ +static inline void lv_ddlist_set_sb_mode(lv_obj_t *ddlist, lv_sb_mode_t mode) { + lv_page_set_sb_mode(ddlist, mode); +} + +/** + * Set the open/close animation time. + * @param ddlist pointer to a drop down list + * @param anim_time: open/close animation time [ms] + */ +void lv_ddlist_set_anim_time(lv_obj_t *ddlist, uint16_t anim_time); + +/** + * Set a style of a drop down list + * @param ddlist pointer to a drop down list object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_ddlist_set_style(lv_obj_t *ddlist, lv_ddlist_style_t type, + lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the options of a drop down list + * @param ddlist pointer to drop down list object + * @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3") + */ +const char *lv_ddlist_get_options(lv_obj_t *ddlist); + +/** + * Get the selected option + * @param ddlist pointer to drop down list object + * @return id of the selected option (0 ... number of option - 1); + */ +uint16_t lv_ddlist_get_selected(lv_obj_t *ddlist); + +/** + * Get the current selected option as a string + * @param ddlist pointer to ddlist object + * @param buf pointer to an array to store the string + */ +void lv_ddlist_get_selected_str(lv_obj_t *ddlist, char *buf); + +/** + * Get the "option selected" callback function + * @param ddlist pointer to a drop down list + * @return pointer to the call back function + */ +lv_action_t lv_ddlist_get_action(lv_obj_t *ddlist); + +/** + * Get the fix height value. + * @param ddlist pointer to a drop down list object + * @return the height if the ddlist is opened (0: auto size) + */ +lv_coord_t lv_ddlist_get_fix_height(lv_obj_t *ddlist); + +/** + * Get the scroll bar mode of a drop down list + * @param ddlist pointer to a drop down list object + * @return scrollbar mode from 'lv_page_sb_mode_t' enum + */ +static inline lv_sb_mode_t lv_ddlist_get_sb_mode(lv_obj_t *ddlist) { + return lv_page_get_sb_mode(ddlist); +} + +/** + * Get the open/close animation time. + * @param ddlist pointer to a drop down list + * @return open/close animation time [ms] + */ +uint16_t lv_ddlist_get_anim_time(lv_obj_t *ddlist); + +/** + * Get a style of a drop down list + * @param ddlist pointer to a drop down list object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_ddlist_get_style(lv_obj_t *ddlist, lv_ddlist_style_t type); + +/*===================== + * Other functions + *====================*/ + +/** + * Open the drop down list with or without animation + * @param ddlist pointer to drop down list object + * @param anim_en true: use animation; false: not use animations + */ +void lv_ddlist_open(lv_obj_t *ddlist, bool anim); + +/** + * Close (Collapse) the drop down list + * @param ddlist pointer to drop down list object + * @param anim true: use animation; false: not use animations + */ +void lv_ddlist_close_en(lv_obj_t *ddlist, bool anim); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_DDLIST*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_DDLIST_H*/ diff --git a/include/display/lv_objx/lv_gauge.h b/include/display/lv_objx/lv_gauge.h new file mode 100644 index 0000000..5b00a09 --- /dev/null +++ b/include/display/lv_objx/lv_gauge.h @@ -0,0 +1,213 @@ +/** + * @file lv_gauge.h + * + */ + +#ifndef LV_GAUGE_H +#define LV_GAUGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_GAUGE != 0 + +/*Testing of dependencies*/ +#if USE_LV_LMETER == 0 +#error \ + "lv_gauge: lv_lmeter is required. Enable it in lv_conf.h (USE_LV_LMETER 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_label.h" +#include "display/lv_objx/lv_line.h" +#include "display/lv_objx/lv_lmeter.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of gauge*/ +typedef struct { + lv_lmeter_ext_t lmeter; /*Ext. of ancestor*/ + /*New data for this type */ + int16_t *values; /*Array of the set values (for needles) */ + const lv_color_t * + needle_colors; /*Color of the needles (lv_color_t my_colors[needle_num])*/ + uint8_t needle_count; /*Number of needles*/ + uint8_t label_count; /*Number of labels on the scale*/ +} lv_gauge_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a gauge objects + * @param par pointer to an object, it will be the parent of the new gauge + * @param copy pointer to a gauge object, if not NULL then the new object will + * be copied from it + * @return pointer to the created gauge + */ +lv_obj_t *lv_gauge_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the number of needles + * @param gauge pointer to gauge object + * @param needle_cnt new count of needles + * @param colors an array of colors for needles (with 'num' elements) + */ +void lv_gauge_set_needle_count(lv_obj_t *gauge, uint8_t needle_cnt, + const lv_color_t *colors); + +/** + * Set the value of a needle + * @param gauge pointer to a gauge + * @param needle_id the id of the needle + * @param value the new value + */ +void lv_gauge_set_value(lv_obj_t *gauge, uint8_t needle_id, int16_t value); + +/** + * Set minimum and the maximum values of a gauge + * @param gauge pointer to he gauge object + * @param min minimum value + * @param max maximum value + */ +static inline void lv_gauge_set_range(lv_obj_t *gauge, int16_t min, + int16_t max) { + lv_lmeter_set_range(gauge, min, max); +} + +/** + * Set a critical value on the scale. After this value 'line.color' scale lines + * will be drawn + * @param gauge pointer to a gauge object + * @param value the critical value + */ +static inline void lv_gauge_set_critical_value(lv_obj_t *gauge, int16_t value) { + lv_lmeter_set_value(gauge, value); +} + +/** + * Set the scale settings of a gauge + * @param gauge pointer to a gauge object + * @param angle angle of the scale (0..360) + * @param line_cnt count of scale lines + * @param label_cnt count of scale labels + */ +void lv_gauge_set_scale(lv_obj_t *gauge, uint16_t angle, uint8_t line_cnt, + uint8_t label_cnt); + +/** + * Set the styles of a gauge + * @param gauge pointer to a gauge object + * @param bg set the style of the gauge + * */ +static inline void lv_gauge_set_style(lv_obj_t *gauge, lv_style_t *bg) { + lv_obj_set_style(gauge, bg); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a needle + * @param gauge pointer to gauge object + * @param needle the id of the needle + * @return the value of the needle [min,max] + */ +int16_t lv_gauge_get_value(lv_obj_t *gauge, uint8_t needle); + +/** + * Get the count of needles on a gauge + * @param gauge pointer to gauge + * @return count of needles + */ +uint8_t lv_gauge_get_needle_count(lv_obj_t *gauge); + +/** + * Get the minimum value of a gauge + * @param gauge pointer to a gauge object + * @return the minimum value of the gauge + */ +static inline int16_t lv_gauge_get_min_value(lv_obj_t *lmeter) { + return lv_lmeter_get_min_value(lmeter); +} + +/** + * Get the maximum value of a gauge + * @param gauge pointer to a gauge object + * @return the maximum value of the gauge + */ +static inline int16_t lv_gauge_get_max_value(lv_obj_t *lmeter) { + return lv_lmeter_get_max_value(lmeter); +} + +/** + * Get a critical value on the scale. + * @param gauge pointer to a gauge object + * @return the critical value + */ +static inline int16_t lv_gauge_get_critical_value(lv_obj_t *gauge) { + return lv_lmeter_get_value(gauge); +} + +/** + * Set the number of labels (and the thicker lines too) + * @param gauge pointer to a gauge object + * @return count of labels + */ +uint8_t lv_gauge_get_label_count(lv_obj_t *gauge); + +/** + * Get the scale number of a gauge + * @param gauge pointer to a gauge object + * @return number of the scale units + */ +static inline uint8_t lv_gauge_get_line_count(lv_obj_t *gauge) { + return lv_lmeter_get_line_count(gauge); +} + +/** + * Get the scale angle of a gauge + * @param gauge pointer to a gauge object + * @return angle of the scale + */ +static inline uint16_t lv_gauge_get_scale_angle(lv_obj_t *gauge) { + return lv_lmeter_get_scale_angle(gauge); +} + +/** + * Get the style of a gauge + * @param gauge pointer to a gauge object + * @return pointer to the gauge's style + */ +static inline lv_style_t *lv_gauge_get_style(lv_obj_t *gauge) { + return lv_obj_get_style(gauge); +} + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_GAUGE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_GAUGE_H*/ diff --git a/include/display/lv_objx/lv_img.h b/include/display/lv_objx/lv_img.h new file mode 100644 index 0000000..44fba13 --- /dev/null +++ b/include/display/lv_objx/lv_img.h @@ -0,0 +1,169 @@ +/** + * @file lv_img.h + * + */ + +#ifndef LV_IMG_H +#define LV_IMG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_IMG != 0 + +#include "display/lv_core/lv_obj.h" +#include "display/lv_draw/lv_draw.h" +#include "display/lv_misc/lv_fonts/lv_symbol_def.h" +#include "display/lv_misc/lv_fs.h" +#include "display/lv_objx/lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of image*/ +typedef struct { + /*No inherited ext. because inherited from the base object*/ /*Ext. of + ancestor*/ + /*New data for this type */ + const void *src; /*Image source: Pointer to an array or a file or a symbol*/ + + lv_coord_t + w; /*Width of the image (doubled when upscaled) (Handled by the library)*/ + lv_coord_t h; /*Height of the image (doubled when upscaled) (Handled by the + library)*/ + uint8_t src_type : 2; /*See: lv_img_src_t*/ + uint8_t + auto_size : 1; /*1: automatically set the object size to the image size*/ + uint8_t + chroma_keyed : 1; /*1: Chroma keyed image, LV_COLOR_TRANSP (lv_conf.h) + pixels will be transparent (Handled by the library)*/ + uint8_t alpha_byte : 1; /*1: Extra byte for every pixel to define opacity*/ +} lv_img_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image objects + * @param par pointer to an object, it will be the parent of the new button + * @param copy pointer to a image object, if not NULL then the new object will + * be copied from it + * @return pointer to the created image + */ +lv_obj_t *lv_img_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the pixel map to display by the image + * @param img pointer to an image object + * @param data the image data + */ +void lv_img_set_src(lv_obj_t *img, const void *src_img); + +/** + * Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in + * v6.0. + * Use 'lv_img_set_src()' instead. + * @param img + * @param fn + */ +static inline void lv_img_set_file(lv_obj_t *img, const char *fn) {} + +/** + * Enable the auto size feature. + * If enabled the object size will be same as the picture size. + * @param img pointer to an image + * @param autosize_en true: auto size enable, false: auto size disable + */ +void lv_img_set_auto_size(lv_obj_t *img, bool autosize_en); + +/** + * Set the style of an image + * @param img pointer to an image object + * @param style pointer to a style + */ +static inline void lv_img_set_style(lv_obj_t *img, lv_style_t *style) { + lv_obj_set_style(img, style); +} + +/** + * Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in + * v6.0 + * @param img + * @param upscale + */ +static inline void lv_img_set_upscale(lv_obj_t *img, bool upcale) {} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the type of an image source + * @param src pointer to an image source: + * - pointer to an 'lv_img_t' variable (image stored internally and compiled + * into the code) + * - a path to an file (e.g. "S:/folder/image.bin") + * - or a symbol (e.g. SYMBOL_CLOSE) + * @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN + */ +lv_img_src_t lv_img_get_src_type(const void *src); + +/** + * Get the name of the file set for an image + * @param img pointer to an image + * @return file name + */ +const char *lv_img_get_file_name(lv_obj_t *img); + +/** + * Get the auto size enable attribute + * @param img pointer to an image + * @return true: auto size is enabled, false: auto size is disabled + */ +bool lv_img_get_auto_size(lv_obj_t *img); + +/** + * Get the style of an image object + * @param img pointer to an image object + * @return pointer to the image's style + */ +static inline lv_style_t *lv_img_get_style(lv_obj_t *img) { + return lv_obj_get_style(img); +} + +/** + * Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in + * v6.0 + * @param img + * @return false + */ +static inline bool lv_img_get_upscale(lv_obj_t *img) { return false; } + +/********************** + * MACROS + **********************/ + +/*Use this macro to declare an image in a c file*/ +#define LV_IMG_DECLARE(var_name) extern const lv_img_t var_name; + +#endif /*USE_LV_IMG*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_IMG_H*/ diff --git a/include/display/lv_objx/lv_kb.h b/include/display/lv_objx/lv_kb.h new file mode 100644 index 0000000..a3bbcb8 --- /dev/null +++ b/include/display/lv_objx/lv_kb.h @@ -0,0 +1,192 @@ +/** + * @file lv_kb.h + * + */ + +#ifndef LV_KB_H +#define LV_KB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_KB != 0 + +/*Testing of dependencies*/ +#if USE_LV_BTNM == 0 +#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) " +#endif + +#if USE_LV_TA == 0 +#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (USE_LV_TA 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btnm.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_KB_MODE_TEXT, + LV_KB_MODE_NUM, +} lv_kb_mode_t; + +/*Data of keyboard*/ +typedef struct { + lv_btnm_ext_t btnm; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *ta; /*Pointer to the assigned text area*/ + lv_kb_mode_t mode; /*Key map type*/ + uint8_t cursor_mng : 1; /*1: automatically show/hide cursor when a text area + is assigned or left*/ + lv_action_t ok_action; /*Called when the "Ok" button is clicked*/ + lv_action_t hide_action; /*Called when the "Hide" button is clicked*/ +} lv_kb_ext_t; + +typedef enum { + LV_KB_STYLE_BG, + LV_KB_STYLE_BTN_REL, + LV_KB_STYLE_BTN_PR, + LV_KB_STYLE_BTN_TGL_REL, + LV_KB_STYLE_BTN_TGL_PR, + LV_KB_STYLE_BTN_INA, +} lv_kb_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a keyboard objects + * @param par pointer to an object, it will be the parent of the new keyboard + * @param copy pointer to a keyboard object, if not NULL then the new object + * will be copied from it + * @return pointer to the created keyboard + */ +lv_obj_t *lv_kb_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Assign a Text Area to the Keyboard. The pressed characters will be put there. + * @param kb pointer to a Keyboard object + * @param ta pointer to a Text Area object to write there + */ +void lv_kb_set_ta(lv_obj_t *kb, lv_obj_t *ta); + +/** + * Set a new a mode (text or number map) + * @param kb pointer to a Keyboard object + * @param mode the mode from 'lv_kb_mode_t' + */ +void lv_kb_set_mode(lv_obj_t *kb, lv_kb_mode_t mode); + +/** + * Automatically hide or show the cursor of the current Text Area + * @param kb pointer to a Keyboard object + * @param en true: show cursor on the current text area, false: hide cursor + */ +void lv_kb_set_cursor_manage(lv_obj_t *kb, bool en); + +/** + * Set call back to call when the "Ok" button is pressed + * @param kb pointer to Keyboard object + * @param action a callback with 'lv_action_t' type + */ +void lv_kb_set_ok_action(lv_obj_t *kb, lv_action_t action); + +/** + * Set call back to call when the "Hide" button is pressed + * @param kb pointer to Keyboard object + * @param action a callback with 'lv_action_t' type + */ +void lv_kb_set_hide_action(lv_obj_t *kb, lv_action_t action); + +/** + * Set a new map for the keyboard + * @param kb pointer to a Keyboard object + * @param map pointer to a string array to describe the map. + * See 'lv_btnm_set_map()' for more info. + */ +static inline void lv_kb_set_map(lv_obj_t *kb, const char **map) { + lv_btnm_set_map(kb, map); +} + +/** + * Set a style of a keyboard + * @param kb pointer to a keyboard object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_kb_set_style(lv_obj_t *kb, lv_kb_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Assign a Text Area to the Keyboard. The pressed characters will be put there. + * @param kb pointer to a Keyboard object + * @return pointer to the assigned Text Area object + */ +lv_obj_t *lv_kb_get_ta(lv_obj_t *kb); + +/** + * Set a new a mode (text or number map) + * @param kb pointer to a Keyboard object + * @return the current mode from 'lv_kb_mode_t' + */ +lv_kb_mode_t lv_kb_get_mode(lv_obj_t *kb); + +/** + * Get the current cursor manage mode. + * @param kb pointer to a Keyboard object + * @return true: show cursor on the current text area, false: hide cursor + */ +bool lv_kb_get_cursor_manage(lv_obj_t *kb); + +/** + * Get the callback to call when the "Ok" button is pressed + * @param kb pointer to Keyboard object + * @return the ok callback + */ +lv_action_t lv_kb_get_ok_action(lv_obj_t *kb); + +/** + * Get the callback to call when the "Hide" button is pressed + * @param kb pointer to Keyboard object + * @return the close callback + */ +lv_action_t lv_kb_get_hide_action(lv_obj_t *kb); + +/** + * Get a style of a keyboard + * @param kb pointer to a keyboard object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_kb_get_style(lv_obj_t *kb, lv_kb_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_KB*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_KB_H*/ diff --git a/include/display/lv_objx/lv_label.h b/include/display/lv_objx/lv_label.h new file mode 100644 index 0000000..d61c01b --- /dev/null +++ b/include/display/lv_objx/lv_label.h @@ -0,0 +1,289 @@ +/** + * @file lv_rect.h + * + */ + +#ifndef LV_LABEL_H +#define LV_LABEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_LABEL != 0 + +#include "display/lv_core/lv_obj.h" +#include "display/lv_misc/lv_font.h" +#include "display/lv_misc/lv_fonts/lv_symbol_def.h" +#include "display/lv_misc/lv_txt.h" + +/********************* + * DEFINES + *********************/ +#define LV_LABEL_DOT_NUM 3 +#define LV_LABEL_POS_LAST 0xFFFF + +/********************** + * TYPEDEFS + **********************/ + +/*Long mode behaviors. Used in 'lv_label_ext_t' */ +typedef enum { + LV_LABEL_LONG_EXPAND, /*Expand the object size to the text size*/ + LV_LABEL_LONG_BREAK, /*Keep the object width, break the too long lines and + expand the object height*/ + LV_LABEL_LONG_SCROLL, /*Expand the object size and scroll the text on the + parent (move the label object)*/ + LV_LABEL_LONG_DOT, /*Keep the size and write dots at the end if the text is + too long*/ + LV_LABEL_LONG_ROLL, /*Keep the size and roll the text infinitely*/ +} lv_label_long_mode_t; + +/*Label align policy*/ +typedef enum { + LV_LABEL_ALIGN_LEFT, + LV_LABEL_ALIGN_CENTER, +} lv_label_align_t; + +/*Data of label*/ +typedef struct { + /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ + /*New data for this type */ + char *text; /*Text of the label*/ + lv_label_long_mode_t long_mode; /*Determinate what to do with the long texts*/ +#if LV_TXT_UTF8 == 0 + char dot_tmp[LV_LABEL_DOT_NUM + 1]; /*Store the character which are replaced + by dots (Handled by the library)*/ +#else + char dot_tmp[LV_LABEL_DOT_NUM * 4 + 1]; /*Store the character which are + replaced by dots (Handled by the + library)*/ +#endif + uint16_t + dot_end; /*The text end position in dot mode (Handled by the library)*/ + uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ + lv_point_t offset; /*Text draw position offset*/ + uint8_t static_txt : 1; /*Flag to indicate the text is static*/ + uint8_t align : 2; /*Align type from 'lv_label_align_t'*/ + uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ + uint8_t expand : 1; /*Ignore real width (used by the library with + LV_LABEL_LONG_ROLL)*/ + uint8_t no_break : 1; /*Ignore new line characters*/ + uint8_t body_draw : 1; /*Draw background body*/ +} lv_label_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a label objects + * @param par pointer to an object, it will be the parent of the new label + * @param copy pointer to a button object, if not NULL then the new object will + * be copied from it + * @return pointer to the created button + */ +lv_obj_t *lv_label_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new text for a label. Memory will be allocated to store the text by the + * label. + * @param label pointer to a label object + * @param text '\0' terminated character string. NULL to refresh with the + * current text. + */ +void lv_label_set_text(lv_obj_t *label, const char *text); + +/** + * Set a new text for a label from a character array. The array don't has to be + * '\0' terminated. + * Memory will be allocated to store the array by the label. + * @param label pointer to a label object + * @param array array of characters or NULL to refresh the label + * @param size the size of 'array' in bytes + */ +void lv_label_set_array_text(lv_obj_t *label, const char *array, uint16_t size); + +/** + * Set a static text. It will not be saved by the label so the 'text' variable + * has to be 'alive' while the label exist. + * @param label pointer to a label object + * @param text pointer to a text. NULL to refresh with the current text. + */ +void lv_label_set_static_text(lv_obj_t *label, const char *text); + +/** + * Set the behavior of the label with longer text then the object size + * @param label pointer to a label object + * @param long_mode the new mode from 'lv_label_long_mode' enum. + */ +void lv_label_set_long_mode(lv_obj_t *label, lv_label_long_mode_t long_mode); + +/** + * Set the align of the label (left or center) + * @param label pointer to a label object + * @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT' + */ +void lv_label_set_align(lv_obj_t *label, lv_label_align_t align); + +/** + * Enable the recoloring by in-line commands + * @param label pointer to a label object + * @param recolor_en true: enable recoloring, false: disable + */ +void lv_label_set_recolor(lv_obj_t *label, bool recolor_en); + +/** + * Set the label to ignore (or accept) line breaks on '\n' + * @param label pointer to a label object + * @param no_break_en true: ignore line breaks, false: make line breaks on '\n' + */ +void lv_label_set_no_break(lv_obj_t *label, bool no_break_en); + +/** + * Set the label to draw (or not draw) background specified in its style's body + * @param label pointer to a label object + * @param body_en true: draw body; false: don't draw body + */ +void lv_label_set_body_draw(lv_obj_t *label, bool body_en); + +/** + * Set the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes + * @param label pointer to a label object + * @param anim_speed speed of animation in px/sec unit + */ +void lv_label_set_anim_speed(lv_obj_t *label, uint16_t anim_speed); + +/** + * Set the style of an label + * @param label pointer to an label object + * @param style pointer to a style + */ +static inline void lv_label_set_style(lv_obj_t *label, lv_style_t *style) { + lv_obj_set_style(label, style); +} +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a label + * @param label pointer to a label object + * @return the text of the label + */ +char *lv_label_get_text(lv_obj_t *label); + +/** + * Get the long mode of a label + * @param label pointer to a label object + * @return the long mode + */ +lv_label_long_mode_t lv_label_get_long_mode(lv_obj_t *label); + +/** + * Get the align attribute + * @param label pointer to a label object + * @return LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER + */ +lv_label_align_t lv_label_get_align(lv_obj_t *label); + +/** + * Get the recoloring attribute + * @param label pointer to a label object + * @return true: recoloring is enabled, false: disable + */ +bool lv_label_get_recolor(lv_obj_t *label); + +/** + * Get the no break attribute + * @param label pointer to a label object + * @return true: no_break_enabled (ignore '\n' line breaks); false: make line + * breaks on '\n' + */ +bool lv_label_get_no_break(lv_obj_t *label); +/** + * Get the body draw attribute + * @param label pointer to a label object + * @return true: draw body; false: don't draw body + */ +bool lv_label_get_body_draw(lv_obj_t *label); + +/** + * Get the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes + * @param label pointer to a label object + * @return speed of animation in px/sec unit + */ +uint16_t lv_label_get_anim_speed(lv_obj_t *label); + +/** + * Get the relative x and y coordinates of a letter + * @param label pointer to a label object + * @param index index of the letter [0 ... text length]. Expressed in character + * index, not byte index (different in UTF-8) + * @param pos store the result here (E.g. index = 0 gives 0;0 coordinates) + */ +void lv_label_get_letter_pos(lv_obj_t *label, uint16_t index, lv_point_t *pos); + +/** + * Get the index of letter on a relative point of a label + * @param label pointer to label object + * @param pos pointer to point with coordinates on a the label + * @return the index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. + * letter) + * Expressed in character index and not byte index (different in UTF-8) + */ +uint16_t lv_label_get_letter_on(lv_obj_t *label, lv_point_t *pos); + +/** + * Get the style of an label object + * @param label pointer to an label object + * @return pointer to the label's style + */ +static inline lv_style_t *lv_label_get_style(lv_obj_t *label) { + return lv_obj_get_style(label); +} + +/*===================== + * Other functions + *====================*/ + +/** + * Insert a text to the label. The label text can not be static. + * @param label pointer to a label object + * @param pos character index to insert. Expressed in character index and not + * byte index (Different in UTF-8) + * 0: before first char. + * LV_LABEL_POS_LAST: after last char. + * @param txt pointer to the text to insert + */ +void lv_label_ins_text(lv_obj_t *label, uint32_t pos, const char *txt); + +/** + * Delete characters from a label. The label text can not be static. + * @param label pointer to a label object + * @param pos character index to insert. Expressed in character index and not + * byte index (Different in UTF-8) + * 0: before first char. + * @param cnt number of characters to cut + */ +void lv_label_cut_text(lv_obj_t *label, uint32_t pos, uint32_t cnt); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_LABEL*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LABEL_H*/ diff --git a/include/display/lv_objx/lv_led.h b/include/display/lv_objx/lv_led.h new file mode 100644 index 0000000..7c2bef8 --- /dev/null +++ b/include/display/lv_objx/lv_led.h @@ -0,0 +1,109 @@ +/** + * @file lv_led.h + * + */ + +#ifndef LV_LED_H +#define LV_LED_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_LED != 0 + +#include "display/lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of led*/ +typedef struct { + /*No inherited ext.*/ + /*New data for this type */ + uint8_t bright; /*Current brightness of the LED (0..255)*/ +} lv_led_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a led objects + * @param par pointer to an object, it will be the parent of the new led + * @param copy pointer to a led object, if not NULL then the new object will be + * copied from it + * @return pointer to the created led + */ +lv_obj_t *lv_led_create(lv_obj_t *par, lv_obj_t *copy); + +/** + * Set the brightness of a LED object + * @param led pointer to a LED object + * @param bright 0 (max. dark) ... 255 (max. light) + */ +void lv_led_set_bright(lv_obj_t *led, uint8_t bright); + +/** + * Light on a LED + * @param led pointer to a LED object + */ +void lv_led_on(lv_obj_t *led); + +/** + * Light off a LED + * @param led pointer to a LED object + */ +void lv_led_off(lv_obj_t *led); + +/** + * Toggle the state of a LED + * @param led pointer to a LED object + */ +void lv_led_toggle(lv_obj_t *led); + +/** + * Set the style of a led + * @param led pointer to a led object + * @param style pointer to a style + */ +static inline void lv_led_set_style(lv_obj_t *led, lv_style_t *style) { + lv_obj_set_style(led, style); +} + +/** + * Get the brightness of a LEd object + * @param led pointer to LED object + * @return bright 0 (max. dark) ... 255 (max. light) + */ +uint8_t lv_led_get_bright(lv_obj_t *led); + +/** + * Get the style of an led object + * @param led pointer to an led object + * @return pointer to the led's style + */ +static inline lv_style_t *lv_led_get_style(lv_obj_t *led) { + return lv_obj_get_style(led); +} + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_LED*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LED_H*/ diff --git a/include/display/lv_objx/lv_line.h b/include/display/lv_objx/lv_line.h new file mode 100644 index 0000000..0a33984 --- /dev/null +++ b/include/display/lv_objx/lv_line.h @@ -0,0 +1,144 @@ +/** + * @file lv_line.h + * + */ + +#ifndef LV_LINE_H +#define LV_LINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_LINE != 0 + +#include "display/lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of line*/ +typedef struct { + /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ + const lv_point_t + *point_array; /*Pointer to an array with the points of the line*/ + uint16_t point_num; /*Number of points in 'point_array' */ + uint8_t + auto_size : 1; /*1: set obj. width to x max and obj. height to y max */ + uint8_t y_inv : 1; /*1: y == 0 will be on the bottom*/ +} lv_line_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a line objects + * @param par pointer to an object, it will be the parent of the new line + * @return pointer to the created line + */ +lv_obj_t *lv_line_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set an array of points. The line object will connect these points. + * @param line pointer to a line object + * @param point_a an array of points. Only the address is saved, + * so the array can NOT be a local variable which will be destroyed + * @param point_num number of points in 'point_a' + */ +void lv_line_set_points(lv_obj_t *line, const lv_point_t *point_a, + uint16_t point_num); + +/** + * Enable (or disable) the auto-size option. The size of the object will fit to + * its points. + * (set width to x max and height to y max) + * @param line pointer to a line object + * @param autosize_en true: auto size is enabled, false: auto size is disabled + */ +void lv_line_set_auto_size(lv_obj_t *line, bool autosize_en); + +/** + * Enable (or disable) the y coordinate inversion. + * If enabled then y will be subtracted from the height of the object, + * therefore the y=0 coordinate will be on the bottom. + * @param line pointer to a line object + * @param yinv_en true: enable the y inversion, false:disable the y inversion + */ +void lv_line_set_y_invert(lv_obj_t *line, bool yinv_en); + +/** + * Set the style of a line + * @param line pointer to a line object + * @param style pointer to a style + */ +static inline void lv_line_set_style(lv_obj_t *line, lv_style_t *style) { + lv_obj_set_style(line, style); +} + +/** + * Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in + * v6.0 + * @param line + * @param upscale + */ +static inline void lv_line_set_upscale(lv_obj_t *line, bool upcale) {} +/*===================== + * Getter functions + *====================*/ + +/** + * Get the auto size attribute + * @param line pointer to a line object + * @return true: auto size is enabled, false: disabled + */ +bool lv_line_get_auto_size(lv_obj_t *line); + +/** + * Get the y inversion attribute + * @param line pointer to a line object + * @return true: y inversion is enabled, false: disabled + */ +bool lv_line_get_y_inv(lv_obj_t *line); + +/** + * Get the style of an line object + * @param line pointer to an line object + * @return pointer to the line's style + */ +static inline lv_style_t *lv_line_get_style(lv_obj_t *line) { + return lv_obj_get_style(line); +} + +/** + * Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in + * v6.0 + * @param line + * @return false + */ +static inline bool lv_line_get_upscale(lv_obj_t *line) { return false; } + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_LINE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LINE_H*/ diff --git a/include/display/lv_objx/lv_list.h b/include/display/lv_objx/lv_list.h new file mode 100644 index 0000000..b1a67a1 --- /dev/null +++ b/include/display/lv_objx/lv_list.h @@ -0,0 +1,204 @@ +/** + * @file lv_list.h + * + */ + +#ifndef LV_LIST_H +#define LV_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_LIST != 0 + +/*Testing of dependencies*/ +#if USE_LV_PAGE == 0 +#error "lv_list: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) " +#endif + +#if USE_LV_BTN == 0 +#error "lv_list: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) " +#endif + +#if USE_LV_LABEL == 0 +#error \ + "lv_list: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btn.h" +#include "display/lv_objx/lv_img.h" +#include "display/lv_objx/lv_label.h" +#include "display/lv_objx/lv_page.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of list*/ +typedef struct { + lv_page_ext_t page; /*Ext. of ancestor*/ + /*New data for this type */ + uint16_t anim_time; /*Scroll animation time*/ + lv_style_t + *styles_btn[LV_BTN_STATE_NUM]; /*Styles of the list element buttons*/ + lv_style_t *style_img; /*Style of the list element images on buttons*/ +} lv_list_ext_t; + +typedef enum { + LV_LIST_STYLE_BG, + LV_LIST_STYLE_SCRL, + LV_LIST_STYLE_SB, + LV_LIST_STYLE_BTN_REL, + LV_LIST_STYLE_BTN_PR, + LV_LIST_STYLE_BTN_TGL_REL, + LV_LIST_STYLE_BTN_TGL_PR, + LV_LIST_STYLE_BTN_INA, +} lv_list_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a list objects + * @param par pointer to an object, it will be the parent of the new list + * @param copy pointer to a list object, if not NULL then the new object will be + * copied from it + * @return pointer to the created list + */ +lv_obj_t *lv_list_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Add a list element to the list + * @param list pointer to list object + * @param img_fn file name of an image before the text (NULL if unused) + * @param txt text of the list element (NULL if unused) + * @param rel_action pointer to release action function (like with lv_btn) + * @return pointer to the new list element which can be customized (a button) + */ +lv_obj_t *lv_list_add(lv_obj_t *list, const void *img_src, const char *txt, + lv_action_t rel_action); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set scroll animation duration on 'list_up()' 'list_down()' 'list_focus()' + * @param list pointer to a list object + * @param anim_time duration of animation [ms] + */ +void lv_list_set_anim_time(lv_obj_t *list, uint16_t anim_time); + +/** + * Set the scroll bar mode of a list + * @param list pointer to a list object + * @param sb_mode the new mode from 'lv_page_sb_mode_t' enum + */ +static inline void lv_list_set_sb_mode(lv_obj_t *list, lv_sb_mode_t mode) { + lv_page_set_sb_mode(list, mode); +} + +/** + * Set a style of a list + * @param list pointer to a list object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_list_set_style(lv_obj_t *list, lv_list_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a list element + * @param btn pointer to list element + * @return pointer to the text + */ +const char *lv_list_get_btn_text(lv_obj_t *btn); +/** + * Get the label object from a list element + * @param btn pointer to a list element (button) + * @return pointer to the label from the list element or NULL if not found + */ +lv_obj_t *lv_list_get_btn_label(lv_obj_t *btn); + +/** + * Get the image object from a list element + * @param btn pointer to a list element (button) + * @return pointer to the image from the list element or NULL if not found + */ +lv_obj_t *lv_list_get_btn_img(lv_obj_t *btn); + +/** + * Get scroll animation duration + * @param list pointer to a list object + * @return duration of animation [ms] + */ +uint16_t lv_list_get_anim_time(lv_obj_t *list); + +/** + * Get the scroll bar mode of a list + * @param list pointer to a list object + * @return scrollbar mode from 'lv_page_sb_mode_t' enum + */ +static inline lv_sb_mode_t lv_list_get_sb_mode(lv_obj_t *list) { + return lv_page_get_sb_mode(list); +} + +/** + * Get a style of a list + * @param list pointer to a list object + * @param type which style should be get + * @return style pointer to a style + * */ +lv_style_t *lv_list_get_style(lv_obj_t *list, lv_list_style_t type); + +/*===================== + * Other functions + *====================*/ + +/** + * Move the list elements up by one + * @param list pointer a to list object + */ +void lv_list_up(lv_obj_t *list); +/** + * Move the list elements down by one + * @param list pointer to a list object + */ +void lv_list_down(lv_obj_t *list); + +/** + * Focus on a list button. It ensures that the button will be visible on the + * list. + * @param btn pointer to a list button to focus + * @param anim_en true: scroll with animation, false: without animation + */ +void lv_list_focus(lv_obj_t *btn, bool anim_en); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_LIST*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LIST_H*/ diff --git a/include/display/lv_objx/lv_lmeter.h b/include/display/lv_objx/lv_lmeter.h new file mode 100644 index 0000000..3f9149e --- /dev/null +++ b/include/display/lv_objx/lv_lmeter.h @@ -0,0 +1,146 @@ +/** + * @file lv_lmeter.h + * + */ + +#ifndef LV_LMETER_H +#define LV_LMETER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_LMETER != 0 + +#include "display/lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of line meter*/ +typedef struct { + /*No inherited ext.*/ /*Ext. of ancestor*/ + /*New data for this type */ + uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/ + uint8_t line_cnt; /*Count of lines */ + int16_t cur_value; + int16_t min_value; + int16_t max_value; +} lv_lmeter_ext_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a line meter objects + * @param par pointer to an object, it will be the parent of the new line meter + * @param copy pointer to a line meter object, if not NULL then the new object + * will be copied from it + * @return pointer to the created line meter + */ +lv_obj_t *lv_lmeter_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the line meter + * @param lmeter pointer to a line meter object + * @param value new value + */ +void lv_lmeter_set_value(lv_obj_t *lmeter, int16_t value); + +/** + * Set minimum and the maximum values of a line meter + * @param lmeter pointer to he line meter object + * @param min minimum value + * @param max maximum value + */ +void lv_lmeter_set_range(lv_obj_t *lmeter, int16_t min, int16_t max); + +/** + * Set the scale settings of a line meter + * @param lmeter pointer to a line meter object + * @param angle angle of the scale (0..360) + * @param line_cnt number of lines + */ +void lv_lmeter_set_scale(lv_obj_t *lmeter, uint16_t angle, uint8_t line_cnt); + +/** + * Set the styles of a line meter + * @param lmeter pointer to a line meter object + * @param bg set the style of the line meter + * */ +static inline void lv_lmeter_set_style(lv_obj_t *lmeter, lv_style_t *bg) { + lv_obj_set_style(lmeter, bg); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a line meter + * @param lmeter pointer to a line meter object + * @return the value of the line meter + */ +int16_t lv_lmeter_get_value(lv_obj_t *lmeter); + +/** + * Get the minimum value of a line meter + * @param lmeter pointer to a line meter object + * @return the minimum value of the line meter + */ +int16_t lv_lmeter_get_min_value(lv_obj_t *lmeter); + +/** + * Get the maximum value of a line meter + * @param lmeter pointer to a line meter object + * @return the maximum value of the line meter + */ +int16_t lv_lmeter_get_max_value(lv_obj_t *lmeter); + +/** + * Get the scale number of a line meter + * @param lmeter pointer to a line meter object + * @return number of the scale units + */ +uint8_t lv_lmeter_get_line_count(lv_obj_t *lmeter); + +/** + * Get the scale angle of a line meter + * @param lmeter pointer to a line meter object + * @return angle of the scale + */ +uint16_t lv_lmeter_get_scale_angle(lv_obj_t *lmeter); + +/** + * Get the style of a line meter + * @param lmeter pointer to a line meter object + * @return pointer to the line meter's style + */ +static inline lv_style_t *lv_lmeter_get_style_bg(lv_obj_t *lmeter) { + return lv_obj_get_style(lmeter); +} + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_LMETER*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LMETER_H*/ diff --git a/include/display/lv_objx/lv_mbox.h b/include/display/lv_objx/lv_mbox.h new file mode 100644 index 0000000..26490eb --- /dev/null +++ b/include/display/lv_objx/lv_mbox.h @@ -0,0 +1,184 @@ +/** + * @file lv_mbox.h + * + */ + +#ifndef LV_MBOX_H +#define LV_MBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_MBOX != 0 + +/*Testing of dependencies*/ +#if USE_LV_CONT == 0 +#error "lv_mbox: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) " +#endif + +#if USE_LV_BTNM == 0 +#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) " +#endif + +#if USE_LV_LABEL == 0 +#error \ + "lv_mbox: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btnm.h" +#include "display/lv_objx/lv_cont.h" +#include "display/lv_objx/lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of message box*/ +typedef struct { + lv_cont_ext_t bg; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *text; /*Text of the message box*/ + lv_obj_t *btnm; /*Button matrix for the buttons*/ + uint16_t anim_time; /*Duration of close animation [ms] (0: no animation)*/ +} lv_mbox_ext_t; + +typedef enum { + LV_MBOX_STYLE_BG, + LV_MBOX_STYLE_BTN_BG, + LV_MBOX_STYLE_BTN_REL, + LV_MBOX_STYLE_BTN_PR, + LV_MBOX_STYLE_BTN_TGL_REL, + LV_MBOX_STYLE_BTN_TGL_PR, + LV_MBOX_STYLE_BTN_INA, +} lv_mbox_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a message box objects + * @param par pointer to an object, it will be the parent of the new message box + * @param copy pointer to a message box object, if not NULL then the new object + * will be copied from it + * @return pointer to the created message box + */ +lv_obj_t *lv_mbox_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Add button to the message box + * @param mbox pointer to message box object + * @param btn_map button descriptor (button matrix map). + * E.g. a const char *txt[] = {"ok", "close", ""} (Can not be + * local variable) + * @param action a function which will be called when a button is released + */ +void lv_mbox_add_btns(lv_obj_t *mbox, const char **btn_map, + lv_btnm_action_t action); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the text of the message box + * @param mbox pointer to a message box + * @param txt a '\0' terminated character string which will be the message box + * text + */ +void lv_mbox_set_text(lv_obj_t *mbox, const char *txt); + +/** + * Stop the action to call when button is released + * @param mbox pointer to a message box object + * @param pointer to an 'lv_btnm_action_t' action + */ +void lv_mbox_set_action(lv_obj_t *mbox, lv_btnm_action_t action); + +/** + * Set animation duration + * @param mbox pointer to a message box object + * @param anim_time animation length in milliseconds (0: no animation) + */ +void lv_mbox_set_anim_time(lv_obj_t *mbox, uint16_t anim_time); + +/** + * Automatically delete the message box after a given time + * @param mbox pointer to a message box object + * @param delay a time (in milliseconds) to wait before delete the message box + */ +void lv_mbox_start_auto_close(lv_obj_t *mbox, uint16_t delay); + +/** + * Stop the auto. closing of message box + * @param mbox pointer to a message box object + */ +void lv_mbox_stop_auto_close(lv_obj_t *mbox); + +/** + * Set a style of a message box + * @param mbox pointer to a message box object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_mbox_set_style(lv_obj_t *mbox, lv_mbox_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of the message box + * @param mbox pointer to a message box object + * @return pointer to the text of the message box + */ +const char *lv_mbox_get_text(lv_obj_t *mbox); + +/** + * Get the message box object from one of its button. + * It is useful in the button release actions where only the button is known + * @param btn pointer to a button of a message box + * @return pointer to the button's message box + */ +lv_obj_t *lv_mbox_get_from_btn(lv_obj_t *btn); + +/** + * Get the animation duration (close animation time) + * @param mbox pointer to a message box object + * @return animation length in milliseconds (0: no animation) + */ +uint16_t lv_mbox_get_anim_time(lv_obj_t *mbox); + +/** + * Get a style of a message box + * @param mbox pointer to a message box object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_mbox_get_style(lv_obj_t *mbox, lv_mbox_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_MBOX*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_MBOX_H*/ diff --git a/include/display/lv_objx/lv_objx.mk b/include/display/lv_objx/lv_objx.mk new file mode 100644 index 0000000..4a4e3e2 --- /dev/null +++ b/include/display/lv_objx/lv_objx.mk @@ -0,0 +1,28 @@ +CSRCS += lv_bar.c +CSRCS += lv_cb.c +CSRCS += lv_ddlist.c +CSRCS += lv_kb.c +CSRCS += lv_line.c +CSRCS += lv_mbox.c +CSRCS += lv_roller.c +CSRCS += lv_tabview.c +CSRCS += lv_btn.c +CSRCS += lv_chart.c +CSRCS += lv_gauge.c +CSRCS += lv_label.c +CSRCS += lv_list.c +CSRCS += lv_slider.c +CSRCS += lv_ta.c +CSRCS += lv_btnm.c +CSRCS += lv_cont.c +CSRCS += lv_img.c +CSRCS += lv_led.c +CSRCS += lv_lmeter.c +CSRCS += lv_page.c +CSRCS += lv_sw.c +CSRCS += lv_win.c + +DEPPATH += --dep-path lvgl/lv_objx +VPATH += :lvgl/lv_objx + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_objx" diff --git a/include/display/lv_objx/lv_objx_templ.h b/include/display/lv_objx/lv_objx_templ.h new file mode 100644 index 0000000..bd481ac --- /dev/null +++ b/include/display/lv_objx/lv_objx_templ.h @@ -0,0 +1,106 @@ +/** + * @file lv_templ.h + * + */ + +/* TODO Remove these instructions + * Search an replace: template -> object normal name with lower case (e.g. + * button, label etc.) + * templ -> object short name with lower case(e.g. btn, label + * etc) + * TEMPL -> object short name with upper case (e.g. BTN, + * LABEL etc.) + * + */ + +#ifndef LV_TEMPL_H +#define LV_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_TEMPL != 0 + +#include "display/lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of template*/ +typedef struct { + lv_ANCESTOR_ext_t ANCESTOR; /*Ext. of ancestor*/ + /*New data for this type */ +} lv_templ_ext_t; + +/*Styles*/ +typedef enum { + LV_TEMPL_STYLE_X, + LV_TEMPL_STYLE_Y, +} lv_templ_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a template objects + * @param par pointer to an object, it will be the parent of the new template + * @param copy pointer to a template object, if not NULL then the new object + * will be copied from it + * @return pointer to the created template + */ +lv_obj_t *lv_templ_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a style of a template. + * @param templ pointer to template object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_templ_set_style(lv_obj_t *templ, lv_templ_style_t type, + lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get style of a template. + * @param templ pointer to template object + * @param type which style should be get + * @return style pointer to the style + * */ +lv_style_t *lv_btn_get_style(lv_obj_t *templ, lv_templ_style_t type); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_TEMPL*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TEMPL_H*/ diff --git a/include/display/lv_objx/lv_page.h b/include/display/lv_objx/lv_page.h new file mode 100644 index 0000000..4283af6 --- /dev/null +++ b/include/display/lv_objx/lv_page.h @@ -0,0 +1,260 @@ +/** + * @file lv_page.h + * + */ + +#ifndef LV_PAGE_H +#define LV_PAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_PAGE != 0 + +/*Testing of dependencies*/ +#if USE_LV_CONT == 0 +#error "lv_page: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) " +#endif + +#include "display/lv_core/lv_indev.h" +#include "display/lv_objx/lv_cont.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Scrollbar modes: shows when should the scrollbars be visible*/ +typedef enum { + LV_SB_MODE_OFF, /*Never show scrollbars*/ + LV_SB_MODE_ON, /*Always show scrollbars*/ + LV_SB_MODE_DRAG, /*Show scrollbars when page is being dragged*/ + LV_SB_MODE_AUTO, /*Show scrollbars when the scrollable container is large + enough to be scrolled*/ +} lv_sb_mode_t; + +/*Data of page*/ +typedef struct { + lv_cont_ext_t bg; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *scrl; /*The scrollable object on the background*/ + lv_action_t rel_action; /*Function to call when the page is released*/ + lv_action_t pr_action; /*Function to call when the page is pressed*/ + struct { + lv_style_t *style; /*Style of scrollbars*/ + lv_area_t hor_area; /*Horizontal scrollbar area relative to the page. + (Handled by the library) */ + lv_area_t ver_area; /*Vertical scrollbar area relative to the page (Handled + by the library)*/ + uint8_t hor_draw : 1; /*1: horizontal scrollbar is visible now (Handled by + the library)*/ + uint8_t ver_draw : 1; /*1: vertical scrollbar is visible now (Handled by the + library)*/ + uint8_t mode : 3; /*Scrollbar visibility from 'lv_page_sb_mode_t'*/ + } sb; +} lv_page_ext_t; + +typedef enum { + LV_PAGE_STYLE_BG, + LV_PAGE_STYLE_SCRL, + LV_PAGE_STYLE_SB, +} lv_page_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a page objects + * @param par pointer to an object, it will be the parent of the new page + * @param copy pointer to a page object, if not NULL then the new object will be + * copied from it + * @return pointer to the created page + */ +lv_obj_t *lv_page_create(lv_obj_t *par, lv_obj_t *copy); + +/** + * Get the scrollable object of a page + * @param page pointer to a page object + * @return pointer to a container which is the scrollable part of the page + */ +lv_obj_t *lv_page_get_scrl(lv_obj_t *page); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a release action for the page + * @param page pointer to a page object + * @param rel_action a function to call when the page is released + */ +void lv_page_set_rel_action(lv_obj_t *page, lv_action_t rel_action); + +/** + * Set a press action for the page + * @param page pointer to a page object + * @param pr_action a function to call when the page is pressed + */ +void lv_page_set_pr_action(lv_obj_t *page, lv_action_t pr_action); + +/** + * Set the scroll bar mode on a page + * @param page pointer to a page object + * @param sb.mode the new mode from 'lv_page_sb.mode_t' enum + */ +void lv_page_set_sb_mode(lv_obj_t *page, lv_sb_mode_t sb_mode); + +/** + * Set the fit attribute of the scrollable part of a page. + * It means it can set its size automatically to involve all children. + * (Can be set separately horizontally and vertically) + * @param page pointer to a page object + * @param hor_en true: enable horizontal fit + * @param ver_en true: enable vertical fit + */ +static inline void lv_page_set_scrl_fit(lv_obj_t *page, bool hor_en, + bool ver_en) { + lv_cont_set_fit(lv_page_get_scrl(page), hor_en, ver_en); +} + +/** + * Set width of the scrollable part of a page + * @param page pointer to a page object + * @param w the new width of the scrollable (it ha no effect is horizontal fit + * is enabled) + */ +static inline void lv_page_set_scrl_width(lv_obj_t *page, lv_coord_t w) { + lv_obj_set_width(lv_page_get_scrl(page), w); +} + +/** + * Set height of the scrollable part of a page + * @param page pointer to a page object + * @param h the new height of the scrollable (it ha no effect is vertical fit is + * enabled) + */ +static inline void lv_page_set_scrl_height(lv_obj_t *page, lv_coord_t h) { + lv_obj_set_height(lv_page_get_scrl(page), h); +} + +/** +* Set the layout of the scrollable part of the page +* @param page pointer to a page object +* @param layout a layout from 'lv_cont_layout_t' +*/ +static inline void lv_page_set_scrl_layout(lv_obj_t *page, lv_layout_t layout) { + lv_cont_set_layout(lv_page_get_scrl(page), layout); +} + +/** + * Set a style of a page + * @param page pointer to a page object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_page_set_style(lv_obj_t *page, lv_page_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Set the scroll bar mode on a page + * @param page pointer to a page object + * @return the mode from 'lv_page_sb.mode_t' enum + */ +lv_sb_mode_t lv_page_get_sb_mode(lv_obj_t *page); + +/** + * Get width of the scrollable part of a page + * @param page pointer to a page object + * @return the width of the scrollable + */ +static inline lv_coord_t lv_page_get_scrl_width(lv_obj_t *page) { + return lv_obj_get_width(lv_page_get_scrl(page)); +} + +/** + * Get height of the scrollable part of a page + * @param page pointer to a page object + * @return the height of the scrollable + */ +static inline lv_coord_t lv_page_get_scrl_height(lv_obj_t *page) { + return lv_obj_get_height(lv_page_get_scrl(page)); +} + +/** +* Get the layout of the scrollable part of a page +* @param page pointer to page object +* @return the layout from 'lv_cont_layout_t' +*/ +static inline lv_layout_t lv_page_get_scrl_layout(lv_obj_t *page) { + return lv_cont_get_layout(lv_page_get_scrl(page)); +} + +/** +* Get horizontal fit attribute of the scrollable part of a page +* @param page pointer to a page object +* @return true: horizontal fit is enabled; false: disabled +*/ +static inline bool lv_page_get_scrl_hor_fit(lv_obj_t *page) { + return lv_cont_get_hor_fit(lv_page_get_scrl(page)); +} + +/** +* Get vertical fit attribute of the scrollable part of a page +* @param page pointer to a page object +* @return true: vertical fit is enabled; false: disabled +*/ +static inline bool lv_page_get_scrl_fit_ver(lv_obj_t *page) { + return lv_cont_get_ver_fit(lv_page_get_scrl(page)); +} + +/** + * Get a style of a page + * @param page pointer to page object + * @param type which style should be get + * @return style pointer to a style + * */ +lv_style_t *lv_page_get_style(lv_obj_t *page, lv_page_style_t type); + +/*===================== + * Other functions + *====================*/ + +/** + * Glue the object to the page. After it the page can be moved (dragged) with + * this object too. + * @param obj pointer to an object on a page + * @param glue true: enable glue, false: disable glue + */ +void lv_page_glue_obj(lv_obj_t *obj, bool glue); + +/** + * Focus on an object. It ensures that the object will be visible on the page. + * @param page pointer to a page object + * @param obj pointer to an object to focus (must be on the page) + * @param anim_time scroll animation time in milliseconds (0: no animation) + */ +void lv_page_focus(lv_obj_t *page, lv_obj_t *obj, uint16_t anim_time); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_PAGE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_PAGE_H*/ diff --git a/include/display/lv_objx/lv_roller.h b/include/display/lv_objx/lv_roller.h new file mode 100644 index 0000000..c4b82a9 --- /dev/null +++ b/include/display/lv_objx/lv_roller.h @@ -0,0 +1,199 @@ +/** + * @file lv_roller.h + * + */ + +#ifndef LV_ROLLER_H +#define LV_ROLLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_ROLLER != 0 + +/*Testing of dependencies*/ +#if USE_LV_DDLIST == 0 +#error \ + "lv_roller: lv_ddlist is required. Enable it in lv_conf.h (USE_LV_DDLIST 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_ddlist.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of roller*/ +typedef struct { + lv_ddlist_ext_t ddlist; /*Ext. of ancestor*/ + /*New data for this type */ +} lv_roller_ext_t; + +typedef enum { + LV_ROLLER_STYLE_BG, + LV_ROLLER_STYLE_SEL, +} lv_roller_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a roller object + * @param par pointer to an object, it will be the parent of the new roller + * @param copy pointer to a roller object, if not NULL then the new object will + * be copied from it + * @return pointer to the created roller + */ +lv_obj_t *lv_roller_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the options on a roller + * @param roller pointer to roller object + * @param options a string with '\n' separated options. E.g. "One\nTwo\nThree" + */ +static inline void lv_roller_set_options(lv_obj_t *roller, + const char *options) { + lv_ddlist_set_options(roller, options); +} + +/** + * Set the selected option + * @param roller pointer to a roller object + * @param sel_opt id of the selected option (0 ... number of option - 1); + * @param anim_en true: set with animation; false set immediately + */ +void lv_roller_set_selected(lv_obj_t *roller, uint16_t sel_opt, bool anim_en); + +/** + * Set a function to call when a new option is chosen + * @param roller pointer to a roller + * @param action pointer to a callback function + */ +static inline void lv_roller_set_action(lv_obj_t *roller, lv_action_t action) { + lv_ddlist_set_action(roller, action); +} + +/** + * Set the height to show the given number of rows (options) + * @param roller pointer to a roller object + * @param row_cnt number of desired visible rows + */ +void lv_roller_set_visible_row_count(lv_obj_t *roller, uint8_t row_cnt); + +/** + * Enable or disable the horizontal fit to the content + * @param roller pointer to a roller + * @param fit en true: enable auto fit; false: disable auto fit + */ +static inline void lv_roller_set_hor_fit(lv_obj_t *roller, bool fit_en) { + lv_ddlist_set_hor_fit(roller, fit_en); +} + +/** + * Set the open/close animation time. + * @param roller pointer to a roller object + * @param anim_time: open/close animation time [ms] + */ +static inline void lv_roller_set_anim_time(lv_obj_t *roller, + uint16_t anim_time) { + lv_ddlist_set_anim_time(roller, anim_time); +} + +/** + * Set a style of a roller + * @param roller pointer to a roller object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_roller_set_style(lv_obj_t *roller, lv_roller_style_t type, + lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the options of a roller + * @param roller pointer to roller object + * @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3") + */ +static inline const char *lv_roller_get_options(lv_obj_t *roller) { + return lv_ddlist_get_options(roller); +} + +/** + * Get the id of the selected option + * @param roller pointer to a roller object + * @return id of the selected option (0 ... number of option - 1); + */ +static inline uint16_t lv_roller_get_selected(lv_obj_t *roller) { + return lv_ddlist_get_selected(roller); +} + +/** + * Get the current selected option as a string + * @param roller pointer to roller object + * @param buf pointer to an array to store the string + */ +static inline void lv_roller_get_selected_str(lv_obj_t *roller, char *buf) { + lv_ddlist_get_selected_str(roller, buf); +} + +/** + * Get the "option selected" callback function + * @param roller pointer to a roller + * @return pointer to the call back function + */ +static inline lv_action_t lv_roller_get_action(lv_obj_t *roller) { + return lv_ddlist_get_action(roller); +} + +/** + * Get the open/close animation time. + * @param roller pointer to a roller + * @return open/close animation time [ms] + */ +static inline uint16_t lv_roller_get_anim_time(lv_obj_t *roller) { + return lv_ddlist_get_anim_time(roller); +} + +/** + * Get the auto width set attribute + * @param roller pointer to a roller object + * @return true: auto size enabled; false: manual width settings enabled + */ +bool lv_roller_get_hor_fit(lv_obj_t *roller); + +/** + * Get a style of a roller + * @param roller pointer to a roller object + * @param type which style should be get + * @return style pointer to a style + * */ +lv_style_t *lv_roller_get_style(lv_obj_t *roller, lv_roller_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_ROLLER*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ROLLER_H*/ diff --git a/include/display/lv_objx/lv_slider.h b/include/display/lv_objx/lv_slider.h new file mode 100644 index 0000000..4684fb3 --- /dev/null +++ b/include/display/lv_objx/lv_slider.h @@ -0,0 +1,193 @@ +/** + * @file lv_slider.h + * + */ + +#ifndef LV_SLIDER_H +#define LV_SLIDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_SLIDER != 0 + +/*Testing of dependencies*/ +#if USE_LV_BAR == 0 +#error "lv_slider: lv_bar is required. Enable it in lv_conf.h (USE_LV_BAR 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_bar.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of slider*/ +typedef struct { + lv_bar_ext_t bar; /*Ext. of ancestor*/ + /*New data for this type */ + lv_action_t action; /*Function to call when a new value is set*/ + lv_style_t *style_knob; /*Style of the knob*/ + int16_t drag_value; /*Store a temporal value during press until release + (Handled by the library)*/ + uint8_t knob_in : 1; /*1: Draw the knob inside the bar*/ +} lv_slider_ext_t; + +/*Built-in styles of slider*/ +typedef enum { + LV_SLIDER_STYLE_BG, + LV_SLIDER_STYLE_INDIC, + LV_SLIDER_STYLE_KNOB, +} lv_slider_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a slider objects + * @param par pointer to an object, it will be the parent of the new slider + * @param copy pointer to a slider object, if not NULL then the new object will + * be copied from it + * @return pointer to the created slider + */ +lv_obj_t *lv_slider_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the slider + * @param slider pointer to a slider object + * @param value new value + */ +static inline void lv_slider_set_value(lv_obj_t *slider, int16_t value) { + lv_bar_set_value(slider, value); +} + +/** + * Set a new value with animation on a slider + * @param slider pointer to a slider object + * @param value new value + * @param anim_time animation time in milliseconds + */ +static inline void lv_slider_set_value_anim(lv_obj_t *slider, int16_t value, + uint16_t anim_time) { + lv_bar_set_value_anim(slider, value, anim_time); +} + +/** + * Set minimum and the maximum values of a bar + * @param slider pointer to the slider object + * @param min minimum value + * @param max maximum value + */ +static inline void lv_slider_set_range(lv_obj_t *slider, int16_t min, + int16_t max) { + lv_bar_set_range(slider, min, max); +} + +/** + * Set a function which will be called when a new value is set on the slider + * @param slider pointer to slider object + * @param action a callback function + */ +void lv_slider_set_action(lv_obj_t *slider, lv_action_t action); + +/** + * Set the 'knob in' attribute of a slider + * @param slider pointer to slider object + * @param in true: the knob is drawn always in the slider; + * false: the knob can be out on the edges + */ +void lv_slider_set_knob_in(lv_obj_t *slider, bool in); + +/** + * Set a style of a slider + * @param slider pointer to a slider object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_slider_set_style(lv_obj_t *slider, lv_slider_style_t type, + lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a slider + * @param slider pointer to a slider object + * @return the value of the slider + */ +int16_t lv_slider_get_value(lv_obj_t *slider); + +/** + * Get the minimum value of a slider + * @param slider pointer to a slider object + * @return the minimum value of the slider + */ +static inline int16_t lv_slider_get_min_value(lv_obj_t *slider) { + return lv_bar_get_min_value(slider); +} + +/** + * Get the maximum value of a slider + * @param slider pointer to a slider object + * @return the maximum value of the slider + */ +static inline int16_t lv_slider_get_max_value(lv_obj_t *slider) { + return lv_bar_get_max_value(slider); +} + +/** + * Get the slider action function + * @param slider pointer to slider object + * @return the callback function + */ +lv_action_t lv_slider_get_action(lv_obj_t *slider); + +/** + * Give the slider is being dragged or not + * @param slider pointer to a slider object + * @return true: drag in progress false: not dragged + */ +bool lv_slider_is_dragged(lv_obj_t *slider); + +/** + * Get the 'knob in' attribute of a slider + * @param slider pointer to slider object + * @return true: the knob is drawn always in the slider; + * false: the knob can be out on the edges + */ +bool lv_slider_get_knob_in(lv_obj_t *slider); + +/** + * Get a style of a slider + * @param slider pointer to a slider object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_slider_get_style(lv_obj_t *slider, lv_slider_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_SLIDER*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_SLIDER_H*/ diff --git a/include/display/lv_objx/lv_sw.h b/include/display/lv_objx/lv_sw.h new file mode 100644 index 0000000..eb8151a --- /dev/null +++ b/include/display/lv_objx/lv_sw.h @@ -0,0 +1,137 @@ +/** + * @file lv_sw.h + * + */ + +#ifndef LV_SW_H +#define LV_SW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_SW != 0 + +/*Testing of dependencies*/ +#if USE_LV_SLIDER == 0 +#error "lv_sw: lv_slider is required. Enable it in lv_conf.h (USE_LV_SLIDER 1)" +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_slider.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of switch*/ +typedef struct { + lv_slider_ext_t slider; /*Ext. of ancestor*/ + /*New data for this type */ + lv_style_t *style_knob_off; /*Style of the knob when the switch is OFF*/ + lv_style_t *style_knob_on; /*Style of the knob when the switch is ON (NULL to + use the same as OFF)*/ + uint8_t changed : 1; /*Indicates the switch explicitly changed by drag*/ +} lv_sw_ext_t; + +typedef enum { + LV_SW_STYLE_BG, + LV_SW_STYLE_INDIC, + LV_SW_STYLE_KNOB_OFF, + LV_SW_STYLE_KNOB_ON, +} lv_sw_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a switch objects + * @param par pointer to an object, it will be the parent of the new switch + * @param copy pointer to a switch object, if not NULL then the new object will + * be copied from it + * @return pointer to the created switch + */ +lv_obj_t *lv_sw_create(lv_obj_t *par, lv_obj_t *copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Turn ON the switch + * @param sw pointer to a switch object + */ +void lv_sw_on(lv_obj_t *sw); + +/** + * Turn OFF the switch + * @param sw pointer to a switch object + */ +void lv_sw_off(lv_obj_t *sw); + +/** + * Set a function which will be called when the switch is toggled by the user + * @param sw pointer to switch object + * @param action a callback function + */ +static inline void lv_sw_set_action(lv_obj_t *sw, lv_action_t action) { + lv_slider_set_action(sw, action); +} + +/** + * Set a style of a switch + * @param sw pointer to a switch object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_sw_set_style(lv_obj_t *sw, lv_sw_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the state of a switch + * @param sw pointer to a switch object + * @return false: OFF; true: ON + */ +static inline bool lv_sw_get_state(lv_obj_t *sw) { + return lv_bar_get_value(sw) == 0 ? false : true; +} + +/** + * Get the switch action function + * @param slider pointer to a switch object + * @return the callback function + */ +static inline lv_action_t lv_sw_get_action(lv_obj_t *slider) { + return lv_slider_get_action(slider); +} + +/** + * Get a style of a switch + * @param sw pointer to a switch object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_sw_get_style(lv_obj_t *sw, lv_sw_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_SW*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_SW_H*/ diff --git a/include/display/lv_objx/lv_ta.h b/include/display/lv_objx/lv_ta.h new file mode 100644 index 0000000..d807c64 --- /dev/null +++ b/include/display/lv_objx/lv_ta.h @@ -0,0 +1,280 @@ +/** + * @file lv_ta.h + * + */ + +#ifndef LV_TA_H +#define LV_TA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_TA != 0 + +/*Testing of dependencies*/ +#if USE_LV_PAGE == 0 +#error "lv_ta: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) " +#endif + +#if USE_LV_LABEL == 0 +#error "lv_ta: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_label.h" +#include "display/lv_objx/lv_page.h" + +/********************* + * DEFINES + *********************/ +#define LV_TA_CURSOR_LAST (0x7FFF) /*Put the cursor after the last character*/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_CURSOR_NONE, + LV_CURSOR_LINE, + LV_CURSOR_BLOCK, + LV_CURSOR_OUTLINE, + LV_CURSOR_UNDERLINE, + LV_CURSOR_HIDDEN = 0x10, /*Or it to any value to hide the cursor temporally*/ +} lv_cursor_type_t; + +/*Data of text area*/ +typedef struct { + lv_page_ext_t page; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *label; /*Label of the text area*/ + char *pwd_tmp; /*Used to store the original text in password mode*/ + uint8_t pwd_mode : 1; /*Replace characters with '*' */ + uint8_t one_line : 1; /*One line mode (ignore line breaks)*/ + struct { + lv_style_t *style; /*Style of the cursor (NULL to use label's style)*/ + lv_coord_t + valid_x; /*Used when stepping up/down in text area when stepping to a + shorter line. (Handled by the library)*/ + uint16_t + pos; /*The current cursor position (0: before 1. letter; 1: before 2. + letter etc.)*/ + lv_cursor_type_t type; /*Shape of the cursor*/ + uint8_t state : 1; /*Indicates that the cursor is visible now or not + (Handled by the library)*/ + } cursor; +} lv_ta_ext_t; + +typedef enum { + LV_TA_STYLE_BG, + LV_TA_STYLE_SB, + LV_TA_STYLE_CURSOR, +} lv_ta_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a text area objects + * @param par pointer to an object, it will be the parent of the new text area + * @param copy pointer to a text area object, if not NULL then the new object + * will be copied from it + * @return pointer to the created text area + */ +lv_obj_t *lv_ta_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Insert a character to the current cursor position + * @param ta pointer to a text area object + * @param c a character + */ +void lv_ta_add_char(lv_obj_t *ta, char c); + +/** + * Insert a text to the current cursor position + * @param ta pointer to a text area object + * @param txt a '\0' terminated string to insert + */ +void lv_ta_add_text(lv_obj_t *ta, const char *txt); + +/** + * Delete a the left character from the current cursor position + * @param ta pointer to a text area object + */ +void lv_ta_del_char(lv_obj_t *ta); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the text of a text area + * @param ta pointer to a text area + * @param txt pointer to the text + */ +void lv_ta_set_text(lv_obj_t *ta, const char *txt); + +/** + * Set the cursor position + * @param obj pointer to a text area object + * @param pos the new cursor position in character index + * < 0 : index from the end of the text + * LV_TA_CURSOR_LAST: go after the last character + */ +void lv_ta_set_cursor_pos(lv_obj_t *ta, int16_t pos); + +/** + * Set the cursor type. + * @param ta pointer to a text area object + * @param cur_type: element of 'lv_cursor_type_t' + */ +void lv_ta_set_cursor_type(lv_obj_t *ta, lv_cursor_type_t cur_type); +/** + * Enable/Disable password mode + * @param ta pointer to a text area object + * @param pwd_en true: enable, false: disable + */ +void lv_ta_set_pwd_mode(lv_obj_t *ta, bool pwd_en); + +/** + * Configure the text area to one line or back to normal + * @param ta pointer to a Text area object + * @param en true: one line, false: normal + */ +void lv_ta_set_one_line(lv_obj_t *ta, bool en); + +/** + * Set the scroll bar mode of a text area + * @param ta pointer to a text area object + * @param sb_mode the new mode from 'lv_page_sb_mode_t' enum + */ +static inline void lv_ta_set_sb_mode(lv_obj_t *ta, lv_sb_mode_t mode) { + lv_page_set_sb_mode(ta, mode); +} + +/** + * Set a style of a text area + * @param ta pointer to a text area object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_ta_set_style(lv_obj_t *ta, lv_ta_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a text area + * @param ta pointer to a text area object + * @return pointer to the text + */ +const char *lv_ta_get_text(lv_obj_t *ta); + +/** + * Get the label of a text area + * @param ta pointer to a text area object + * @return pointer to the label object + */ +lv_obj_t *lv_ta_get_label(lv_obj_t *ta); + +/** + * Get the current cursor position in character index + * @param ta pointer to a text area object + * @return the cursor position + */ +uint16_t lv_ta_get_cursor_pos(lv_obj_t *ta); + +/** + * Get the current cursor visibility. + * @param ta pointer to a text area object + * @return true: the cursor is drawn, false: the cursor is hidden + */ +bool lv_ta_get_cursor_show(lv_obj_t *ta); + +/** + * Get the current cursor type. + * @param ta pointer to a text area object + * @return element of 'lv_cursor_type_t' + */ +lv_cursor_type_t lv_ta_get_cursor_type(lv_obj_t *ta); + +/** + * Get the password mode attribute + * @param ta pointer to a text area object + * @return true: password mode is enabled, false: disabled + */ +bool lv_ta_get_pwd_mode(lv_obj_t *ta); + +/** + * Get the one line configuration attribute + * @param ta pointer to a text area object + * @return true: one line configuration is enabled, false: disabled + */ +bool lv_ta_get_one_line(lv_obj_t *ta); + +/** + * Get the scroll bar mode of a text area + * @param ta pointer to a text area object + * @return scrollbar mode from 'lv_page_sb_mode_t' enum + */ +static inline lv_sb_mode_t lv_ta_get_sb_mode(lv_obj_t *ta) { + return lv_page_get_sb_mode(ta); +} + +/** + * Get a style of a text area + * @param ta pointer to a text area object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_ta_get_style(lv_obj_t *ta, lv_ta_style_t type); + +/*===================== + * Other functions + *====================*/ + +/** + * Move the cursor one character right + * @param ta pointer to a text area object + */ +void lv_ta_cursor_right(lv_obj_t *ta); + +/** + * Move the cursor one character left + * @param ta pointer to a text area object + */ +void lv_ta_cursor_left(lv_obj_t *ta); + +/** + * Move the cursor one line down + * @param ta pointer to a text area object + */ +void lv_ta_cursor_down(lv_obj_t *ta); + +/** + * Move the cursor one line up + * @param ta pointer to a text area object + */ +void lv_ta_cursor_up(lv_obj_t *ta); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_TA_H*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TA_H*/ diff --git a/include/display/lv_objx/lv_tabview.h b/include/display/lv_objx/lv_tabview.h new file mode 100644 index 0000000..60d1d69 --- /dev/null +++ b/include/display/lv_objx/lv_tabview.h @@ -0,0 +1,209 @@ +/** + * @file lv_tabview.h + * + */ + +#ifndef LV_TABVIEW_H +#define LV_TABVIEW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_TABVIEW != 0 + +/*Testing of dependencies*/ +#if USE_LV_BTNM == 0 +#error \ + "lv_tabview: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) " +#endif + +#if USE_LV_PAGE == 0 +#error \ + "lv_tabview: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_page.h" +#include "display/lv_objx/lv_win.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/* parameters: pointer to a tabview object, tab_id*/ +typedef void (*lv_tabview_action_t)(lv_obj_t *, uint16_t); + +/*Data of tab*/ +typedef struct { + /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *btns; + lv_obj_t *indic; + lv_obj_t *content; /*A rectangle to show the current tab*/ + const char **tab_name_ptr; + lv_point_t point_last; + uint16_t tab_cur; + uint16_t tab_cnt; + uint16_t anim_time; + uint8_t slide_enable : 1; /*1: enable horizontal sliding by touch pad*/ + uint8_t draging : 1; + uint8_t drag_hor : 1; + lv_tabview_action_t tab_load_action; +} lv_tabview_ext_t; + +typedef enum { + LV_TABVIEW_STYLE_BG, + LV_TABVIEW_STYLE_INDIC, + LV_TABVIEW_STYLE_BTN_BG, + LV_TABVIEW_STYLE_BTN_REL, + LV_TABVIEW_STYLE_BTN_PR, + LV_TABVIEW_STYLE_BTN_TGL_REL, + LV_TABVIEW_STYLE_BTN_TGL_PR, +} lv_tabview_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a Tab view object + * @param par pointer to an object, it will be the parent of the new tab + * @param copy pointer to a tab object, if not NULL then the new object will be + * copied from it + * @return pointer to the created tab + */ +lv_obj_t *lv_tabview_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Add a new tab with the given name + * @param tabview pointer to Tab view object where to ass the new tab + * @param name the text on the tab button + * @return pointer to the created page object (lv_page). You can create your + * content here + */ +lv_obj_t *lv_tabview_add_tab(lv_obj_t *tabview, const char *name); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new tab + * @param tabview pointer to Tab view object + * @param id index of a tab to load + * @param anim_en true: set with sliding animation; false: set immediately + */ +void lv_tabview_set_tab_act(lv_obj_t *tabview, uint16_t id, bool anim_en); + +/** + * Set an action to call when a tab is loaded (Good to create content only if + * required) + * lv_tabview_get_act() still gives the current (old) tab (to remove content + * from here) + * @param tabview pointer to a tabview object + * @param action pointer to a function to call when a tab is loaded + */ +void lv_tabview_set_tab_load_action(lv_obj_t *tabview, + lv_tabview_action_t action); + +/** + * Enable horizontal sliding with touch pad + * @param tabview pointer to Tab view object + * @param en true: enable sliding; false: disable sliding + */ +void lv_tabview_set_sliding(lv_obj_t *tabview, bool en); + +/** + * Set the animation time of tab view when a new tab is loaded + * @param tabview pointer to Tab view object + * @param anim_time time of animation in milliseconds + */ +void lv_tabview_set_anim_time(lv_obj_t *tabview, uint16_t anim_time); + +/** + * Set the style of a tab view + * @param tabview pointer to a tan view object + * @param type which style should be set + * @param style pointer to the new style + */ +void lv_tabview_set_style(lv_obj_t *tabview, lv_tabview_style_t type, + lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the index of the currently active tab + * @param tabview pointer to Tab view object + * @return the active tab index + */ +uint16_t lv_tabview_get_tab_act(lv_obj_t *tabview); + +/** + * Get the number of tabs + * @param tabview pointer to Tab view object + * @return tab count + */ +uint16_t lv_tabview_get_tab_count(lv_obj_t *tabview); +/** + * Get the page (content area) of a tab + * @param tabview pointer to Tab view object + * @param id index of the tab (>= 0) + * @return pointer to page (lv_page) object + */ +lv_obj_t *lv_tabview_get_tab(lv_obj_t *tabview, uint16_t id); + +/** + * Get the tab load action + * @param tabview pointer to a tabview object + * @param return the current tab load action + */ +lv_tabview_action_t lv_tabview_get_tab_load_action(lv_obj_t *tabview); + +/** + * Get horizontal sliding is enabled or not + * @param tabview pointer to Tab view object + * @return true: enable sliding; false: disable sliding + */ +bool lv_tabview_get_sliding(lv_obj_t *tabview); + +/** + * Get the animation time of tab view when a new tab is loaded + * @param tabview pointer to Tab view object + * @return time of animation in milliseconds + */ +uint16_t lv_tabview_get_anim_time(lv_obj_t *tabview); + +/** + * Get a style of a tab view + * @param tabview pointer to a ab view object + * @param type which style should be get + * @return style pointer to a style + */ +lv_style_t *lv_tabview_get_style(lv_obj_t *tabview, lv_tabview_style_t type); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_TABVIEW*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TABVIEW_H*/ diff --git a/include/display/lv_objx/lv_win.h b/include/display/lv_objx/lv_win.h new file mode 100644 index 0000000..1d25887 --- /dev/null +++ b/include/display/lv_objx/lv_win.h @@ -0,0 +1,227 @@ +/** + * @file lv_win.h + * + */ + +#ifndef LV_WIN_H +#define LV_WIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#if USE_LV_WIN != 0 + +/*Testing of dependencies*/ +#if USE_LV_BTN == 0 +#error "lv_win: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) " +#endif + +#if USE_LV_LABEL == 0 +#error "lv_win: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) " +#endif + +#if USE_LV_IMG == 0 +#error "lv_win: lv_img is required. Enable it in lv_conf.h (USE_LV_IMG 1) " +#endif + +#if USE_LV_PAGE == 0 +#error "lv_win: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) " +#endif + +#include "display/lv_core/lv_obj.h" +#include "display/lv_objx/lv_btn.h" +#include "display/lv_objx/lv_cont.h" +#include "display/lv_objx/lv_img.h" +#include "display/lv_objx/lv_label.h" +#include "display/lv_objx/lv_page.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of window*/ +typedef struct { + /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t *page; /*Pointer to a page which holds the content*/ + lv_obj_t *header; /*Pointer to the header container of the window*/ + lv_obj_t *title; /*Pointer to the title label of the window*/ + lv_style_t *style_header; /*Style of the header container*/ + lv_style_t *style_btn_rel; /*Control button releases style*/ + lv_style_t *style_btn_pr; /*Control button pressed style*/ + lv_coord_t btn_size; /*Size of the control buttons (square)*/ +} lv_win_ext_t; + +typedef enum { + LV_WIN_STYLE_BG, + LV_WIN_STYLE_CONTENT_BG, + LV_WIN_STYLE_CONTENT_SCRL, + LV_WIN_STYLE_SB, + LV_WIN_STYLE_HEADER, + LV_WIN_STYLE_BTN_REL, + LV_WIN_STYLE_BTN_PR, +} lv_win_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a window objects + * @param par pointer to an object, it will be the parent of the new window + * @param copy pointer to a window object, if not NULL then the new object will + * be copied from it + * @return pointer to the created window + */ +lv_obj_t *lv_win_create(lv_obj_t *par, lv_obj_t *copy); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Add control button to the header of the window + * @param win pointer to a window object + * @param img_src an image source ('lv_img_t' variable, path to file or a + * symbol) + * @param rel_action a function pointer to call when the button is released + * @return pointer to the created button object + */ +lv_obj_t *lv_win_add_btn(lv_obj_t *win, const void *img_src, + lv_action_t rel_action); + +/*===================== + * Setter functions + *====================*/ + +/** + * A release action which can be assigned to a window control button to close it + * @param btn pointer to the released button + * @return always LV_ACTION_RES_INV because the button is deleted with the + * window + */ +lv_res_t lv_win_close_action(lv_obj_t *btn); + +/** + * Set the title of a window + * @param win pointer to a window object + * @param title string of the new title + */ +void lv_win_set_title(lv_obj_t *win, const char *title); + +/** + * Set the control button size of a window + * @param win pointer to a window object + * @return control button size + */ +void lv_win_set_btn_size(lv_obj_t *win, lv_coord_t size); + +/** + * Set the scroll bar mode of a window + * @param win pointer to a window object + * @param sb_mode the new scroll bar mode from 'lv_sb_mode_t' + */ +void lv_win_set_sb_mode(lv_obj_t *win, lv_sb_mode_t sb_mode); + +/** + * Set the layout of the window + * @param win pointer to a window object + * @param layout the layout from 'lv_layout_t' + */ +void lv_win_set_layout(lv_obj_t *win, lv_layout_t layout); + +/** + * Set a style of a window + * @param win pointer to a window object + * @param type which style should be set + * @param style pointer to a style + */ +void lv_win_set_style(lv_obj_t *win, lv_win_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the title of a window + * @param win pointer to a window object + * @return title string of the window + */ +const char *lv_win_get_title(lv_obj_t *win); + +/** + * Get the control button size of a window + * @param win pointer to a window object + * @return control button size + */ +lv_coord_t lv_win_get_btn_size(lv_obj_t *win); + +/** + * Get the layout of a window + * @param win pointer to a window object + * @return the layout of the window (from 'lv_layout_t') + */ +lv_layout_t lv_win_get_layout(lv_obj_t *win); + +/** + * Get the scroll bar mode of a window + * @param win pointer to a window object + * @return the scroll bar mode of the window (from 'lv_sb_mode_t') + */ +lv_sb_mode_t lv_win_get_sb_mode(lv_obj_t *win); + +/** + * Get width of the content area (page scrollable) of the window + * @param win pointer to a window object + * @return the width of the content area + */ +lv_coord_t lv_win_get_width(lv_obj_t *win); + +/** + * Get the pointer of a widow from one of its control button. + * It is useful in the action of the control buttons where only button is known. + * @param ctrl_btn pointer to a control button of a window + * @return pointer to the window of 'ctrl_btn' + */ +lv_obj_t *lv_win_get_from_btn(lv_obj_t *ctrl_btn); + +/** + * Get a style of a window + * @param win pointer to a button object + * @param type which style window be get + * @return style pointer to a style + */ +lv_style_t *lv_win_get_style(lv_obj_t *win, lv_win_style_t type); + +/*===================== + * Other functions + *====================*/ + +/** + * Focus on an object. It ensures that the object will be visible in the window. + * @param win pointer to a window object + * @param obj pointer to an object to focus (must be in the window) + * @param anim_time scroll animation time in milliseconds (0: no animation) + */ +void lv_win_focus(lv_obj_t *win, lv_obj_t *obj, uint16_t anim_time); + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_WIN*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_WIN_H*/ diff --git a/include/display/lv_themes/lv_theme.h b/include/display/lv_themes/lv_theme.h new file mode 100644 index 0000000..d887e51 --- /dev/null +++ b/include/display/lv_themes/lv_theme.h @@ -0,0 +1,267 @@ +/** + *@file lv_themes.h + * + */ + +#ifndef LV_THEMES_H +#define LV_THEMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" +#include "display/lv_core/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_style_t *bg; + lv_style_t *panel; + +#if USE_LV_CONT != 0 + lv_style_t *cont; +#endif +#if USE_LV_BTN != 0 + struct { + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + lv_style_t *ina; + } btn; +#endif + +#if USE_LV_LABEL != 0 + struct { + lv_style_t *prim; + lv_style_t *sec; + lv_style_t *hint; + } label; +#endif + +#if USE_LV_IMG != 0 + struct { + lv_style_t *light; + lv_style_t *dark; + } img; +#endif + +#if USE_LV_LINE != 0 + struct { + lv_style_t *decor; + } line; +#endif + +#if USE_LV_LED != 0 + lv_style_t *led; +#endif + +#if USE_LV_BAR != 0 + struct { + lv_style_t *bg; + lv_style_t *indic; + } bar; +#endif + +#if USE_LV_SLIDER != 0 + struct { + lv_style_t *bg; + lv_style_t *indic; + lv_style_t *knob; + } slider; +#endif + +#if USE_LV_LMETER != 0 + lv_style_t *lmeter; +#endif + +#if USE_LV_GAUGE != 0 + lv_style_t *gauge; +#endif + +#if USE_LV_SW != 0 + struct { + lv_style_t *bg; + lv_style_t *indic; + lv_style_t *knob_off; + lv_style_t *knob_on; + } sw; +#endif + +#if USE_LV_CHART != 0 + lv_style_t *chart; +#endif + +#if USE_LV_CB != 0 + struct { + lv_style_t *bg; + struct { + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + lv_style_t *ina; + } box; + } cb; +#endif + +#if USE_LV_BTNM != 0 + struct { + lv_style_t *bg; + struct { + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + lv_style_t *ina; + } btn; + } btnm; +#endif + +#if USE_LV_KB != 0 + struct { + lv_style_t *bg; + struct { + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + lv_style_t *ina; + } btn; + } kb; +#endif + +#if USE_LV_MBOX != 0 + struct { + lv_style_t *bg; + struct { + lv_style_t *bg; + lv_style_t *rel; + lv_style_t *pr; + } btn; + } mbox; +#endif + +#if USE_LV_PAGE != 0 + struct { + lv_style_t *bg; + lv_style_t *scrl; + lv_style_t *sb; + } page; +#endif + +#if USE_LV_TA != 0 + struct { + lv_style_t *area; + lv_style_t *oneline; + lv_style_t *cursor; + lv_style_t *sb; + } ta; +#endif + +#if USE_LV_LIST + struct { + lv_style_t *bg; + lv_style_t *scrl; + lv_style_t *sb; + struct { + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + lv_style_t *ina; + } btn; + } list; +#endif + +#if USE_LV_DDLIST != 0 + struct { + lv_style_t *bg; + lv_style_t *sel; + lv_style_t *sb; + } ddlist; +#endif + +#if USE_LV_ROLLER != 0 + struct { + lv_style_t *bg; + lv_style_t *sel; + } roller; +#endif + +#if USE_LV_TABVIEW != 0 + struct { + lv_style_t *bg; + lv_style_t *indic; + struct { + lv_style_t *bg; + lv_style_t *rel; + lv_style_t *pr; + lv_style_t *tgl_rel; + lv_style_t *tgl_pr; + } btn; + } tabview; +#endif + +#if USE_LV_WIN != 0 + struct { + lv_style_t *bg; + lv_style_t *sb; + lv_style_t *header; + struct { + lv_style_t *bg; + lv_style_t *scrl; + } content; + struct { + lv_style_t *rel; + lv_style_t *pr; + } btn; + } win; +#endif +} lv_theme_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Set a theme for the system. + * From now, all the created objects will use styles from this theme by default + * @param th pointer to theme (return value of: 'lv_theme_init_xxx()') + */ +void lv_theme_set_current(lv_theme_t *th); + +/** + * Get the current system theme. + * @return pointer to the current system theme. NULL if not set. + */ +lv_theme_t *lv_theme_get_current(void); + +/********************** + * MACROS + **********************/ + +/********************** + * POST INCLUDE + *********************/ +// #include "lv_theme_templ.h" +// #include "lv_theme_default.h" +#include "lv_theme_alien.h" +// #include "lv_theme_night.h" +// #include "lv_theme_mono.h" + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_THEMES_H*/ diff --git a/include/display/lv_themes/lv_theme_alien.h b/include/display/lv_themes/lv_theme_alien.h new file mode 100644 index 0000000..30aa09e --- /dev/null +++ b/include/display/lv_themes/lv_theme_alien.h @@ -0,0 +1,56 @@ +/** + * @file lv_theme_alien.h + * + */ + +#ifndef LV_THEME_ALIEN_H +#define LV_THEME_ALIEN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if USE_LV_THEME_ALIEN + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the alien theme + * @param hue [0..360] hue value from HSV color space to define the theme's base + * color + * @param font pointer to a font (NULL to use the default) + * @return pointer to the initialized theme + */ +lv_theme_t *lv_theme_alien_init(uint16_t hue, lv_font_t *font); +/** + * Get a pointer to the theme + * @return pointer to the theme + */ +lv_theme_t *lv_theme_get_alien(void); + +/********************** + * MACROS + **********************/ + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_THEME_ALIEN_H*/ diff --git a/include/display/lv_themes/lv_theme_templ.h b/include/display/lv_themes/lv_theme_templ.h new file mode 100644 index 0000000..7a9bd64 --- /dev/null +++ b/include/display/lv_themes/lv_theme_templ.h @@ -0,0 +1,57 @@ +/** + * @file lv_theme_templ.h + * + */ + +#ifndef LV_THEME_TEMPL_H +#define LV_THEME_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "display/lv_conf.h" + +#if USE_LV_THEME_TEMPL + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the templ theme + * @param hue [0..360] hue value from HSV color space to define the theme's base + * color + * @param font pointer to a font (NULL to use the default) + * @return pointer to the initialized theme + */ +lv_theme_t *lv_theme_templ_init(uint16_t hue, lv_font_t *font); + +/** + * Get a pointer to the theme + * @return pointer to the theme + */ +lv_theme_t *lv_theme_get_templ(void); + +/********************** + * MACROS + **********************/ + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_THEME_TEMPL_H*/ diff --git a/include/display/lv_themes/lv_themes.mk b/include/display/lv_themes/lv_themes.mk new file mode 100644 index 0000000..7e3b2a2 --- /dev/null +++ b/include/display/lv_themes/lv_themes.mk @@ -0,0 +1,13 @@ +CSRCS += lv_theme_alien.c +CSRCS += lv_theme.c +CSRCS += lv_theme_default.c +CSRCS += lv_theme_night.c +CSRCS += lv_theme_templ.c +CSRCS += lv_theme_zen.c +CSRCS += lv_theme_material.c + + +DEPPATH += --dep-path lvgl/lv_themes +VPATH += :lvgl/lv_themes + +CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_themes" diff --git a/include/display/lvgl.h b/include/display/lvgl.h new file mode 100644 index 0000000..fa6705f --- /dev/null +++ b/include/display/lvgl.h @@ -0,0 +1,80 @@ +/** + * @file lvgl.h + * Include all LittleV GL related headers + */ + +#ifndef LVGL_H +#define LVGL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +/*Test misc. module version*/ +#include "lv_misc/lv_task.h" + +#include "lv_hal/lv_hal.h" + +#include "lv_core/lv_group.h" +#include "lv_core/lv_obj.h" +#include "lv_core/lv_vdb.h" + +#include "lv_themes/lv_theme.h" + +#include "lv_objx/lv_bar.h" +#include "lv_objx/lv_btn.h" +#include "lv_objx/lv_btnm.h" +#include "lv_objx/lv_cb.h" +#include "lv_objx/lv_chart.h" +#include "lv_objx/lv_cont.h" +#include "lv_objx/lv_ddlist.h" +#include "lv_objx/lv_gauge.h" +#include "lv_objx/lv_img.h" +#include "lv_objx/lv_kb.h" +#include "lv_objx/lv_label.h" +#include "lv_objx/lv_led.h" +#include "lv_objx/lv_line.h" +#include "lv_objx/lv_list.h" +#include "lv_objx/lv_lmeter.h" +#include "lv_objx/lv_mbox.h" +#include "lv_objx/lv_page.h" +#include "lv_objx/lv_roller.h" +#include "lv_objx/lv_slider.h" +#include "lv_objx/lv_sw.h" +#include "lv_objx/lv_ta.h" +#include "lv_objx/lv_tabview.h" +#include "lv_objx/lv_win.h" +#pragma GCC diagnostic pop + +/********************* + * DEFINES + *********************/ +/*Current version of LittlevGL*/ +#define LVGL_VERSION_MAJOR 5 +#define LVGL_VERSION_MINOR 1 +#define LVGL_VERSION_PATCH 0 +#define LVGL_VERSION_INFO "" + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} +#endif + +#endif /*LVGL_H*/ diff --git a/include/main.h b/include/main.h new file mode 100644 index 0000000..c995433 --- /dev/null +++ b/include/main.h @@ -0,0 +1,81 @@ +/** + * \file main.h + * + * Contains common definitions and header files used throughout your PROS + * project. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_MAIN_H_ +#define _PROS_MAIN_H_ + +/** + * If defined, some commonly used enums will have preprocessor macros which give + * a shorter, more convenient naming pattern. If this isn't desired, simply + * comment the following line out. + * + * For instance, E_CONTROLLER_MASTER has a shorter name: CONTROLLER_MASTER. + * E_CONTROLLER_MASTER is pedantically correct within the PROS styleguide, but + * not convienent for most student programmers. + */ +#define PROS_USE_SIMPLE_NAMES + +/** + * If defined, C++ literals will be available for use. All literals are in the + * pros::literals namespace. + * + * For instance, you can do `4_mtr = 50` to set motor 4's target velocity to 50 + */ +#define PROS_USE_LITERALS + +#include "api.h" + +/** + * You should add more #includes here + */ +//#include "okapi/api.hpp" +//#include "pros/api_legacy.h" + +/** + * If you find doing pros::Motor() to be tedious and you'd prefer just to do + * Motor, you can use the namespace with the following commented out line. + * + * IMPORTANT: Only the okapi or pros namespace may be used, not both + * concurrently! The okapi namespace will export all symbols inside the pros + * namespace. + */ +// using namespace pros; +// using namespace pros::literals; +// using namespace okapi; + +/** + * Prototypes for the competition control tasks are redefined here to ensure + * that they can be called from user code (i.e. calling autonomous from a + * button press in opcontrol() for testing purposes). + */ +#ifdef __cplusplus +extern "C" { +#endif +void autonomous(void); +void initialize(void); +void disabled(void); +void competition_initialize(void); +void opcontrol(void); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +/** + * You can add C++-only headers here + */ +//#include +#endif + +#endif // _PROS_MAIN_H_ diff --git a/include/okapi/api.hpp b/include/okapi/api.hpp new file mode 100644 index 0000000..1419a26 --- /dev/null +++ b/include/okapi/api.hpp @@ -0,0 +1,92 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisControllerIntegrated.hpp" +#include "okapi/api/chassis/controller/chassisControllerPid.hpp" +#include "okapi/api/chassis/controller/chassisScales.hpp" +#include "okapi/api/chassis/model/readOnlyChassisModel.hpp" +#include "okapi/api/chassis/model/skidSteerModel.hpp" +#include "okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp" +#include "okapi/api/chassis/model/xDriveModel.hpp" +#include "okapi/impl/chassis/controller/chassisControllerFactory.hpp" +#include "okapi/impl/chassis/model/chassisModelFactory.hpp" + +#include "okapi/api/control/async/asyncLinearMotionProfileController.hpp" +#include "okapi/api/control/async/asyncMotionProfileController.hpp" +#include "okapi/api/control/async/asyncPosIntegratedController.hpp" +#include "okapi/api/control/async/asyncPosPidController.hpp" +#include "okapi/api/control/async/asyncVelIntegratedController.hpp" +#include "okapi/api/control/async/asyncVelPidController.hpp" +#include "okapi/api/control/async/asyncWrapper.hpp" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/control/iterative/iterativeMotorVelocityController.hpp" +#include "okapi/api/control/iterative/iterativePosPidController.hpp" +#include "okapi/api/control/iterative/iterativeVelPidController.hpp" +#include "okapi/api/control/util/controllerRunner.hpp" +#include "okapi/api/control/util/flywheelSimulator.hpp" +#include "okapi/api/control/util/pidTuner.hpp" +#include "okapi/api/control/util/settledUtil.hpp" +#include "okapi/impl/control/async/asyncControllerFactory.hpp" +#include "okapi/impl/control/iterative/iterativeControllerFactory.hpp" +#include "okapi/impl/control/util/controllerRunnerFactory.hpp" +#include "okapi/impl/control/util/pidTunerFactory.hpp" +#include "okapi/impl/control/util/settledUtilFactory.hpp" + +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" +#include "okapi/api/device/rotarysensor/rotarySensor.hpp" +#include "okapi/impl/device/adiUltrasonic.hpp" +#include "okapi/impl/device/button/adiButton.hpp" +#include "okapi/impl/device/button/controllerButton.hpp" +#include "okapi/impl/device/controller.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include "okapi/impl/device/motor/motorGroup.hpp" +#include "okapi/impl/device/rotarysensor/adiEncoder.hpp" +#include "okapi/impl/device/rotarysensor/adiGyro.hpp" +#include "okapi/impl/device/rotarysensor/integratedEncoder.hpp" +#include "okapi/impl/device/rotarysensor/potentiometer.hpp" +#include "okapi/impl/device/vision.hpp" + +#include "okapi/api/filter/averageFilter.hpp" +#include "okapi/api/filter/composableFilter.hpp" +#include "okapi/api/filter/demaFilter.hpp" +#include "okapi/api/filter/ekfFilter.hpp" +#include "okapi/api/filter/emaFilter.hpp" +#include "okapi/api/filter/filter.hpp" +#include "okapi/api/filter/filteredControllerInput.hpp" +#include "okapi/api/filter/medianFilter.hpp" +#include "okapi/api/filter/passthroughFilter.hpp" +#include "okapi/api/filter/velMath.hpp" +#include "okapi/impl/filter/velMathFactory.hpp" + +#include "okapi/api/units/QAcceleration.hpp" +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QAngularAcceleration.hpp" +#include "okapi/api/units/QAngularJerk.hpp" +#include "okapi/api/units/QAngularSpeed.hpp" +#include "okapi/api/units/QArea.hpp" +#include "okapi/api/units/QForce.hpp" +#include "okapi/api/units/QFrequency.hpp" +#include "okapi/api/units/QJerk.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/QMass.hpp" +#include "okapi/api/units/QPressure.hpp" +#include "okapi/api/units/QSpeed.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/units/QTorque.hpp" +#include "okapi/api/units/QVolume.hpp" + +#include "okapi/api/util/abstractRate.hpp" +#include "okapi/api/util/abstractTimer.hpp" +#include "okapi/api/util/mathUtil.hpp" +#include "okapi/api/util/supplier.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include "okapi/impl/util/rate.hpp" +#include "okapi/impl/util/timeUtilFactory.hpp" +#include "okapi/impl/util/timer.hpp" diff --git a/include/okapi/api/chassis/controller/chassisController.hpp b/include/okapi/api/chassis/controller/chassisController.hpp new file mode 100644 index 0000000..b36cdd7 --- /dev/null +++ b/include/okapi/api/chassis/controller/chassisController.hpp @@ -0,0 +1,293 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisScales.hpp" +#include "okapi/api/chassis/model/chassisModel.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QLength.hpp" +#include +#include + +namespace okapi { +class ChassisController : public ChassisModel { + public: + /** + * A ChassisController adds a closed-loop layer on top of a ChassisModel. moveDistance and + * turnAngle both use closed-loop control to move the robot. There are passthrough functions for + * everything defined in ChassisModel. + * + * @param imodel underlying ChassisModel + */ + explicit ChassisController(const std::shared_ptr &imodel, + double imaxVelocity, + double imaxVoltage = 12000); + + ~ChassisController() override; + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel + */ + virtual void moveDistance(QLength itarget) = 0; + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + virtual void moveDistance(double itarget) = 0; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel + */ + virtual void moveDistanceAsync(QLength itarget) = 0; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + virtual void moveDistanceAsync(double itarget) = 0; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + virtual void turnAngle(QAngle idegTarget) = 0; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + virtual void turnAngle(double idegTarget) = 0; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + virtual void turnAngleAsync(QAngle idegTarget) = 0; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + virtual void turnAngleAsync(double idegTarget) = 0; + + /** + * Sets whether turns should be mirrored. + * + * @param ishouldMirror whether turns should be mirrored + */ + virtual void setTurnsMirrored(bool ishouldMirror); + + /** + * Delays until the currently executing movement completes. + */ + virtual void waitUntilSettled() = 0; + + /** + * Drive the robot forwards (using open-loop control). + * + * @param ipower motor power + */ + void forward(double ispeed) const override; + + /** + * Drive the robot in an arc (using open-loop control). + * The algorithm is (approximately): + * leftPower = forwardSpeed + yaw + * rightPower = forwardSpeed - yaw + * + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + */ + void driveVector(double iforwardSpeed, double iyaw) const override; + + /** + * Turn the robot clockwise (using open-loop control). + * + * @param ipower motor power + */ + void rotate(double ispeed) const override; + + /** + * Stop the robot (set all the motors to 0). + */ + void stop() override; + + /** + * Drive the robot with a tank drive layout. Uses voltage mode. + * + * @param ileftSpeed left side speed + * @param irightSpeed right side speed + * @param ithreshold deadband on joystick values + */ + void tank(double ileftSpeed, double irightSpeed, double ithreshold = 0) const override; + + /** + * Drive the robot with an arcade drive layout. + * + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + * @param ithreshold deadband on joystick values + */ + void arcade(double iforwardSpeed, double iyaw, double ithreshold = 0) const override; + + /** + * Power the left side motors. + * + * @param ipower motor power + */ + void left(double ispeed) const override; + + /** + * Power the right side motors. + * + * @param ipower motor power + */ + void right(double ispeed) const override; + + /** + * Read the sensors. + * + * @return sensor readings in the format {left, right} + */ + std::valarray getSensorVals() const override; + + /** + * Reset the sensors to their zero point. + */ + void resetSensors() const override; + + /** + * Set the brake mode for each motor. + * + * @param mode new brake mode + */ + void setBrakeMode(AbstractMotor::brakeMode mode) const override; + + /** + * Set the encoder units for each motor. + * + * @param units new motor encoder units + */ + void setEncoderUnits(AbstractMotor::encoderUnits units) const override; + + /** + * Set the gearset for each motor. + * + * @param gearset new motor gearset + */ + void setGearing(AbstractMotor::gearset gearset) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + */ + void setPosPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + */ + void setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + */ + void setVelPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + */ + void setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Sets a new maximum velocity in RPM [0-600]. + * + * @param imaxVelocity the new maximum velocity + */ + void setMaxVelocity(double imaxVelocity) override; + + /** + * Sets a new maximum voltage in mV [0-12000]. + * + * @param imaxVoltage the new maximum voltage + */ + void setMaxVoltage(double imaxVoltage) override; + + /** + * Get the underlying ChassisModel. This should be used sparingly and carefully because it can + * result in multiple owners writing to the same set of motors. + */ + std::shared_ptr getChassisModel() const; + + /** + * Get the ChassisScales. + */ + virtual ChassisScales getChassisScales() const = 0; + + /** + * Get the GearsetRatioPair. + */ + virtual AbstractMotor::GearsetRatioPair getGearsetRatioPair() const = 0; + + protected: + std::shared_ptr model; + bool normalTurns{true}; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/controller/chassisControllerIntegrated.hpp b/include/okapi/api/chassis/controller/chassisControllerIntegrated.hpp new file mode 100644 index 0000000..3bea2b2 --- /dev/null +++ b/include/okapi/api/chassis/controller/chassisControllerIntegrated.hpp @@ -0,0 +1,128 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisController.hpp" +#include "okapi/api/control/async/asyncPosIntegratedController.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" + +namespace okapi { +class ChassisControllerIntegrated : public virtual ChassisController { + public: + /** + * ChassisController using the V5 motor's integrated control. Puts the motors into degree units. + * Throws a std::invalid_argument exception if the gear ratio is zero. + * + * @param imodelArgs ChassisModelArgs + * @param ileftControllerArgs left side controller params + * @param irightControllerArgs right side controller params + * @param igearset motor internal gearset and gear ratio + * @param iscales see ChassisScales docs + */ + ChassisControllerIntegrated( + const TimeUtil &itimeUtil, + const std::shared_ptr &imodel, + std::unique_ptr ileftController, + std::unique_ptr irightController, + AbstractMotor::GearsetRatioPair igearset = AbstractMotor::gearset::red, + const ChassisScales &iscales = ChassisScales({1, 1})); + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel + */ + void moveDistance(QLength itarget) override; + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + void moveDistance(double itarget) override; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel + */ + void moveDistanceAsync(QLength itarget) override; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + void moveDistanceAsync(double itarget) override; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + void turnAngle(QAngle idegTarget) override; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + void turnAngle(double idegTarget) override; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + void turnAngleAsync(QAngle idegTarget) override; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + void turnAngleAsync(double idegTarget) override; + + /** + * Delays until the currently executing movement completes. + */ + void waitUntilSettled() override; + + /** + * Stop the robot (set all the motors to 0). + */ + void stop() override; + + /** + * Sets a new maximum velocity in RPM [0-600]. + * + * @param imaxVelocity the new maximum velocity + */ + void setMaxVelocity(double imaxVelocity) override; + + /** + * Get the ChassisScales. + */ + ChassisScales getChassisScales() const override; + + /** + * Get the GearsetRatioPair. + */ + AbstractMotor::GearsetRatioPair getGearsetRatioPair() const override; + + protected: + Logger *logger; + std::unique_ptr rate; + std::unique_ptr leftController; + std::unique_ptr rightController; + int lastTarget; + ChassisScales scales; + AbstractMotor::GearsetRatioPair gearsetRatioPair; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/controller/chassisControllerPid.hpp b/include/okapi/api/chassis/controller/chassisControllerPid.hpp new file mode 100644 index 0000000..8fd19cc --- /dev/null +++ b/include/okapi/api/chassis/controller/chassisControllerPid.hpp @@ -0,0 +1,151 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisController.hpp" +#include "okapi/api/control/iterative/iterativePosPidController.hpp" +#include "okapi/api/util/abstractRate.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include +#include + +namespace okapi { +class ChassisControllerPID : public virtual ChassisController { + public: + /** + * ChassisController using PID control. Puts the motors into encoder degree units. Throws a + * std::invalid_argument exception if the gear ratio is zero. + * + * @param imodelArgs ChassisModelArgs + * @param idistanceController distance PID controller + * @param iangleController angle PID controller (keeps the robot straight) + * @param igearset motor internal gearset and gear ratio + * @param iscales see ChassisScales docs + */ + ChassisControllerPID(const TimeUtil &itimeUtil, + const std::shared_ptr &imodel, + std::unique_ptr idistanceController, + std::unique_ptr iangleController, + std::unique_ptr iturnController, + AbstractMotor::GearsetRatioPair igearset = AbstractMotor::gearset::red, + const ChassisScales &iscales = ChassisScales({1, 1})); + + ChassisControllerPID(ChassisControllerPID &&other) noexcept; + + ~ChassisControllerPID() override; + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel + */ + void moveDistance(QLength itarget) override; + + /** + * Drives the robot straight for a distance (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + void moveDistance(double itarget) override; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel + */ + void moveDistanceAsync(QLength itarget) override; + + /** + * Sets the target distance for the robot to drive straight (using closed-loop control). + * + * @param itarget distance to travel in motor degrees + */ + void moveDistanceAsync(double itarget) override; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + void turnAngle(QAngle idegTarget) override; + + /** + * Turns the robot clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + void turnAngle(double idegTarget) override; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for + */ + void turnAngleAsync(QAngle idegTarget) override; + + /** + * Sets the target angle for the robot to turn clockwise in place (using closed-loop control). + * + * @param idegTarget angle to turn for in motor degrees + */ + void turnAngleAsync(double idegTarget) override; + + /** + * Delays until the currently executing movement completes. + */ + void waitUntilSettled() override; + + /** + * Stop the robot (set all the motors to 0). + */ + void stop() override; + + /** + * Starts the internal thread. This should not be called by normal users. This method is called + * by the ChassisControllerFactory when making a new instance of this class. + */ + void startThread(); + + /** + * Get the ChassisScales. + */ + ChassisScales getChassisScales() const override; + + /** + * Get the GearsetRatioPair. + */ + AbstractMotor::GearsetRatioPair getGearsetRatioPair() const override; + + protected: + Logger *logger; + TimeUtil timeUtil; + std::unique_ptr distancePid; + std::unique_ptr anglePid; + std::unique_ptr turnPid; + ChassisScales scales; + AbstractMotor::GearsetRatioPair gearsetRatioPair; + std::atomic_bool doneLooping{true}; + std::atomic_bool doneLoopingSeen{true}; + std::atomic_bool newMovement{false}; + std::atomic_bool dtorCalled{false}; + QTime threadSleepTime{10_ms}; + + static void trampoline(void *context); + void loop(); + + bool waitForDistanceSettled(); + bool waitForAngleSettled(); + void stopAfterSettled(); + + typedef enum { distance, angle, none } modeType; + modeType mode{none}; + + CrossplatformThread *task{nullptr}; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/controller/chassisScales.hpp b/include/okapi/api/chassis/controller/chassisScales.hpp new file mode 100644 index 0000000..cfb9e20 --- /dev/null +++ b/include/okapi/api/chassis/controller/chassisScales.hpp @@ -0,0 +1,81 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/RQuantity.hpp" +#include +#include + +namespace okapi { +class ChassisScales { + public: + /** + * The two scales a Chassis Controller needs to do all of its closed-loop control. First index is + * the straight scale, second index is the turn scale. The straight scale converts motor degrees + * to meters and the turn scale converts motor degrees to robot turn degrees. Read the clawbot + * programming tutorial for more information behind the meaning of these two numbers. + * + * @param iscales {straight scale, turn scale} + */ + ChassisScales(const std::initializer_list &iscales) { + std::vector vec(iscales); + straight = vec.at(0); + turn = vec.at(1); + wheelDiameter = (360 / (straight * 1_pi)) * meter; + wheelbaseWidth = turn * wheelDiameter; + } + + /** + * The two scales a Chassis Controller needs to do all of its closed-loop control. First index is + * the wheel diameter, second index is the wheelbase width. Read the clawbot programming tutorial + * for more information behind the meaning of these two numbers. + * + * The wheelbase diameter is the center-to-center distance between the wheels (center-to-center + * meaning the width between the centers of both wheels). For example, if you are using four inch + * omni wheels and there are 11.5 inches between the centers of each wheel, you would call the + * constructor like so: + * ChassisScales scales({4_in, 11.5_in}); + * + * Wheel diameter + * + * +-+ + * | | + * v v + * + * +---> === === + * | + + + * | ++---------------++ + * | | | + * Wheelbase Width | | | + * | | | + * | | | + * | ++---------------++ + * | + + + * +---> === === + * + * + * @param iwheelbase {wheel diameter, wheelbase width} + */ + ChassisScales(const std::initializer_list &iwheelbase) { + std::vector vec(iwheelbase); + wheelDiameter = vec.at(0); + wheelbaseWidth = vec.at(1); + straight = static_cast(360 / (wheelDiameter.convert(meter) * 1_pi)); + turn = wheelbaseWidth.convert(meter) / wheelDiameter.convert(meter); + } + + virtual ~ChassisScales() = default; + + double straight; + double turn; + QLength wheelDiameter; + QLength wheelbaseWidth; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/model/chassisModel.hpp b/include/okapi/api/chassis/model/chassisModel.hpp new file mode 100644 index 0000000..9293b86 --- /dev/null +++ b/include/okapi/api/chassis/model/chassisModel.hpp @@ -0,0 +1,197 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/model/readOnlyChassisModel.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include +#include +#include +#include + +namespace okapi { +/** + * A version of the ReadOnlyChassisModel that also supports write methods, such as setting motor + * speed. Because this class can write to motors, there can only be one owner and as such copying + * is disabled. + */ +class ChassisModel : public ReadOnlyChassisModel { + public: + ChassisModel(double imaxVelocity, double imaxVoltage = 12000); + ChassisModel(const ChassisModel &) = delete; + ChassisModel &operator=(const ChassisModel &) = delete; + + /** + * Drive the robot forwards (using open-loop control). + * + * @param ipower motor power + */ + virtual void forward(double ispeed) const = 0; + + /** + * Drive the robot in an arc (using open-loop control). + * The algorithm is (approximately): + * leftPower = forwardSpeed + yaw + * rightPower = forwardSpeed - yaw + * + * @param iforwadSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + */ + virtual void driveVector(double iforwardSpeed, double iyaw) const = 0; + + /** + * Turn the robot clockwise (using open-loop control). + * + * @param ispeed motor power + */ + virtual void rotate(double ispeed) const = 0; + + /** + * Stop the robot (set all the motors to 0). + */ + virtual void stop() = 0; + + /** + * Drive the robot with a tank drive layout. Uses voltage mode. + * + * @param ileftSpeed left side speed + * @param irightSpeed right side speed + * @param ithreshold deadband on joystick values + */ + virtual void tank(double ileftSpeed, double irightSpeed, double ithreshold = 0) const = 0; + + /** + * Drive the robot with an arcade drive layout. Uses voltage mode. + * + * @param iforwardSpeed speed forward direction + * @param iyaw speed around the vertical axis + * @param ithreshold deadband on joystick values + */ + virtual void arcade(double iforwardSpeed, double iyaw, double ithreshold = 0) const = 0; + + /** + * Power the left side motors. + * + * @param ipower motor power + */ + virtual void left(double ispeed) const = 0; + + /** + * Power the right side motors. + * + * @param ipower motor power + */ + virtual void right(double ispeed) const = 0; + + /** + * Reset the sensors to their zero point. + */ + virtual void resetSensors() const = 0; + + /** + * Set the brake mode for each motor. + * + * @param mode new brake mode + */ + virtual void setBrakeMode(AbstractMotor::brakeMode mode) const = 0; + + /** + * Set the encoder units for each motor. + * + * @param units new motor encoder units + */ + virtual void setEncoderUnits(AbstractMotor::encoderUnits units) const = 0; + + /** + * Set the gearset for each motor. + * + * @param gearset new motor gearset + */ + virtual void setGearing(AbstractMotor::gearset gearset) const = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + */ + virtual void setPosPID(double ikF, double ikP, double ikI, double ikD) const = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + */ + virtual void setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + */ + virtual void setVelPID(double ikF, double ikP, double ikI, double ikD) const = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + */ + virtual void setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const = 0; + + /** + * Sets a new maximum velocity in RPM [0-600]. + * + * @param imaxVelocity the new maximum velocity + */ + virtual void setMaxVelocity(double imaxVelocity); + + /** + * Sets a new maximum voltage in mV [0-12000]. + * + * @param imaxVoltage the new maximum voltage + */ + virtual void setMaxVoltage(double imaxVoltage); + + protected: + double maxVelocity; + double maxVoltage; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/model/readOnlyChassisModel.hpp b/include/okapi/api/chassis/model/readOnlyChassisModel.hpp new file mode 100644 index 0000000..c7c8da5 --- /dev/null +++ b/include/okapi/api/chassis/model/readOnlyChassisModel.hpp @@ -0,0 +1,30 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/coreProsAPI.hpp" +#include + +namespace okapi { +/** + * A version of the ChassisModel that only supports read methods, such as querying sensor values. + * This class does not let you write to motors, so it supports having multiple owners and as a + * result copying is enabled. + */ +class ReadOnlyChassisModel { + public: + virtual ~ReadOnlyChassisModel(); + + /** + * Read the sensors. + * + * @return sensor readings (format is implementation dependent) + */ + virtual std::valarray getSensorVals() const = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/model/skidSteerModel.hpp b/include/okapi/api/chassis/model/skidSteerModel.hpp new file mode 100644 index 0000000..8f66fa4 --- /dev/null +++ b/include/okapi/api/chassis/model/skidSteerModel.hpp @@ -0,0 +1,229 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/model/chassisModel.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" + +namespace okapi { +class SkidSteerModel : public ChassisModel { + public: + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +100%, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the left and right motors (using the integrated + * encoders). + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + */ + SkidSteerModel(const std::shared_ptr &ileftSideMotor, + const std::shared_ptr &irightSideMotor, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +100%, the robot should move forward in a straight line. + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + * @param ileftEnc left side encoder + * @param irightEnc right side encoder + */ + SkidSteerModel(const std::shared_ptr &ileftSideMotor, + const std::shared_ptr &irightSideMotor, + const std::shared_ptr &ileftEnc, + const std::shared_ptr &irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Drive the robot forwards (using open-loop control). Uses velocity mode. + * + * @param ispeed motor power + */ + void forward(double ispeed) const override; + + /** + * Drive the robot in an arc (using open-loop control). Uses velocity mode. + * The algorithm is (approximately): + * leftPower = ySpeed + zRotation + * rightPower = ySpeed - zRotation + * + * @param iySpeed speed on y axis (forward) + * @param izRotation speed around z axis (up) + */ + void driveVector(double iySpeed, double izRotation) const override; + + /** + * Turn the robot clockwise (using open-loop control). Uses velocity mode. + * + * @param ispeed motor power + */ + void rotate(double ispeed) const override; + + /** + * Stop the robot (set all the motors to 0). Uses velocity mode. + */ + void stop() override; + + /** + * Drive the robot with a tank drive layout. Uses voltage mode. + * + * @param ileftSpeed left side speed + * @param irightSpeed right side speed + * @param ithreshold deadband on joystick values + */ + void tank(double ileftSpeed, double irightSpeed, double ithreshold = 0) const override; + + /** + * Drive the robot with an arcade drive layout. Uses voltage mode. + * + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + * @param ithreshold deadband on joystick values + */ + void arcade(double iforwardSpeed, double iyaw, double ithreshold = 0) const override; + + /** + * Power the left side motors. Uses velocity mode. + * + * @param ispeed motor power + */ + void left(double ispeed) const override; + + /** + * Power the right side motors. Uses velocity mode. + * + * @param ispeed motor power + */ + void right(double ispeed) const override; + + /** + * Read the sensors. + * + * @return sensor readings in the format {left, right} + */ + std::valarray getSensorVals() const override; + + /** + * Reset the sensors to their zero point. + */ + void resetSensors() const override; + + /** + * Set the brake mode for each motor. + * + * @param mode new brake mode + */ + void setBrakeMode(AbstractMotor::brakeMode mode) const override; + + /** + * Set the encoder units for each motor. + * + * @param units new motor encoder units + */ + void setEncoderUnits(AbstractMotor::encoderUnits units) const override; + + /** + * Set the gearset for each motor. + * + * @param gearset new motor gearset + */ + void setGearing(AbstractMotor::gearset gearset) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setPosPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setVelPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Returns the left side motor. + * + * @return the left side motor + */ + std::shared_ptr getLeftSideMotor() const; + + /** + * Returns the left side motor. + * + * @return the left side motor + */ + std::shared_ptr getRightSideMotor() const; + + protected: + std::shared_ptr leftSideMotor; + std::shared_ptr rightSideMotor; + std::shared_ptr leftSensor; + std::shared_ptr rightSensor; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp b/include/okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp new file mode 100644 index 0000000..0cfb17d --- /dev/null +++ b/include/okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp @@ -0,0 +1,48 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/model/skidSteerModel.hpp" + +namespace okapi { +class ThreeEncoderSkidSteerModel : public SkidSteerModel { + public: + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +100%, the robot should move forward in a straight line. + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + * @param ileftEnc left side encoder + * @param imiddleEnc middle encoder (mounted perpendicular to the left and right side encoders) + * @param irightEnc right side encoder + */ + ThreeEncoderSkidSteerModel(const std::shared_ptr &ileftSideMotor, + const std::shared_ptr &irightSideMotor, + const std::shared_ptr &ileftEnc, + const std::shared_ptr &imiddleEnc, + const std::shared_ptr &irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Read the sensors. + * + * @return sensor readings in the format {left, right, middle} + */ + std::valarray getSensorVals() const override; + + /** + * Reset the sensors to their zero point. + */ + void resetSensors() const override; + + protected: + std::shared_ptr middleSensor; +}; +} // namespace okapi diff --git a/include/okapi/api/chassis/model/xDriveModel.hpp b/include/okapi/api/chassis/model/xDriveModel.hpp new file mode 100644 index 0000000..e543c4a --- /dev/null +++ b/include/okapi/api/chassis/model/xDriveModel.hpp @@ -0,0 +1,264 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/model/chassisModel.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" + +namespace okapi { +class XDriveModel : public ChassisModel { + public: + /** + * Model for an x drive (wheels at 45 deg from a skid steer drive). When all motors are powered + * +100%, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the top left and top right motors (using the + * integrated encoders). + * + * @param itopLeftMotor top left motor + * @param itopRightMotor top right motor + * @param ibottomRightMotor bottom right motor + * @param ibottomLeftMotor bottom left motor + */ + XDriveModel(const std::shared_ptr &itopLeftMotor, + const std::shared_ptr &itopRightMotor, + const std::shared_ptr &ibottomRightMotor, + const std::shared_ptr &ibottomLeftMotor, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for an x drive (wheels at 45 deg from a skid steer drive). When all motors are powered + * +100%, the robot should move forward in a straight line. + * + * @param itopLeftMotor top left motor + * @param itopRightMotor top right motor + * @param ibottomRightMotor bottom right motor + * @param ibottomLeftMotor bottom left motor + * @param ileftEnc Left side encoder + * @param irightEnc Right side encoder + */ + XDriveModel(const std::shared_ptr &itopLeftMotor, + const std::shared_ptr &itopRightMotor, + const std::shared_ptr &ibottomRightMotor, + const std::shared_ptr &ibottomLeftMotor, + const std::shared_ptr &ileftEnc, + const std::shared_ptr &irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Drive the robot forwards (using open-loop control). Uses velocity mode. + * + * @param ispeed motor power + */ + void forward(double ipower) const override; + + /** + * Drive the robot in an arc (using open-loop control). Uses velocity mode. + * The algorithm is (approximately): + * leftPower = forwardSpeed + yaw + * rightPower = forwardSpeed - yaw + * + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + */ + void driveVector(double iforwardSpeed, double iyaw) const override; + + /** + * Turn the robot clockwise (using open-loop control). Uses velocity mode. + * + * @param ipower motor power + */ + void rotate(double ipower) const override; + + /** + * Stop the robot (set all the motors to 0). Uses velocity mode. + */ + void stop() override; + + /** + * Drive the robot with a tank drive layout. Uses voltage mode. + * + * @param ileftSpeed left side speed + * @param irightSpeed right side speed + * @param ithreshold deadband on joystick values + */ + void tank(double ileftSpeed, double irightSpeed, double ithreshold = 0) const override; + + /** + * Drive the robot with an arcade drive layout. Uses voltage mode. + * + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + * @param ithreshold deadband on joystick values + */ + void arcade(double iforwardSpeed, double iyaw, double ithreshold = 0) const override; + + /** + * Drive the robot with an arcade drive layout. Uses voltage mode. + * + * @param irightSpeed speed to the right + * @param iforwardSpeed speed in the forward direction + * @param iyaw speed around the vertical axis + * @param ithreshold deadband on joystick values + */ + virtual void + xArcade(double irightSpeed, double iforwardSpeed, double iyaw, double ithreshold = 0) const; + + /** + * Power the left side motors. Uses velocity mode. + * + * @param ipower motor power + */ + void left(double ipower) const override; + + /** + * Power the right side motors. Uses velocity mode. + * + * @param ipower motor power + */ + void right(double ipower) const override; + + /** + * Read the sensors. + * + * @return sensor readings in the format {left, right} + */ + std::valarray getSensorVals() const override; + + /** + * Reset the sensors to their zero point. + */ + void resetSensors() const override; + + /** + * Set the brake mode for each motor. + * + * @param mode new brake mode + */ + void setBrakeMode(AbstractMotor::brakeMode mode) const override; + + /** + * Set the encoder units for each motor. + * + * @param units new motor encoder units + */ + void setEncoderUnits(AbstractMotor::encoderUnits units) const override; + + /** + * Set the gearset for each motor. + * + * @param gearset new motor gearset + */ + void setGearing(AbstractMotor::gearset gearset) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setPosPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setVelPID(double ikF, double ikP, double ikI, double ikD) const override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + void setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) const override; + + /** + * Returns the top left motor. + * + * @return the top left motor + */ + std::shared_ptr getTopLeftMotor() const; + + /** + * Returns the top right motor. + * + * @return the top right motor + */ + std::shared_ptr getTopRightMotor() const; + + /** + * Returns the bottom right motor. + * + * @return the bottom right motor + */ + std::shared_ptr getBottomRightMotor() const; + + /** + * Returns the bottom left motor. + * + * @return the bottom left motor + */ + std::shared_ptr getBottomLeftMotor() const; + + protected: + std::shared_ptr topLeftMotor; + std::shared_ptr topRightMotor; + std::shared_ptr bottomRightMotor; + std::shared_ptr bottomLeftMotor; + std::shared_ptr leftSensor; + std::shared_ptr rightSensor; +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncController.hpp b/include/okapi/api/control/async/asyncController.hpp new file mode 100644 index 0000000..3636fe9 --- /dev/null +++ b/include/okapi/api/control/async/asyncController.hpp @@ -0,0 +1,26 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/closedLoopController.hpp" + +namespace okapi { +/** + * Closed-loop controller that steps on its own in another thread and automatically writes to the + * output. + */ +template +class AsyncController : public ClosedLoopController { + public: + /** + * Blocks the current task until the controller has settled. Determining what settling means is + * implementation-dependent. + */ + virtual void waitUntilSettled() = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncLinearMotionProfileController.hpp b/include/okapi/api/control/async/asyncLinearMotionProfileController.hpp new file mode 100644 index 0000000..d2f3e38 --- /dev/null +++ b/include/okapi/api/control/async/asyncLinearMotionProfileController.hpp @@ -0,0 +1,194 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncPositionController.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include +#include + +extern "C" { +#include "okapi/pathfinder/include/pathfinder.h" +} + +namespace okapi { +class AsyncLinearMotionProfileController : public AsyncPositionController { + public: + /** + * An Async Controller which generates and follows 1D motion profiles. + * + * @param imaxVel The maximum possible velocity. + * @param imaxAccel The maximum possible acceleration. + * @param imaxJerk The maximum possible jerk. + * @param ioutput The output to write velocity targets to. + */ + AsyncLinearMotionProfileController(const TimeUtil &itimeUtil, + double imaxVel, + double imaxAccel, + double imaxJerk, + const std::shared_ptr> &ioutput); + + AsyncLinearMotionProfileController(AsyncLinearMotionProfileController &&other) noexcept; + + ~AsyncLinearMotionProfileController() override; + + /** + * Generates a path which intersects the given waypoints and saves it internally with a key of + * pathId. Call executePath() with the same pathId to run it. + * + * If the waypoints form a path which is impossible to achieve, an instance of std::runtime_error + * is thrown (and an error is logged) which describes the waypoints. If there are no waypoints, + * no path is generated. + * + * @param iwaypoints The waypoints to hit on the path. + * @param ipathId A unique identifier to save the path with. + */ + void generatePath(std::initializer_list iwaypoints, const std::string &ipathId); + + /** + * Removes a path and frees the memory it used. + * + * @param ipathId A unique identifier for the path, previously passed to generatePath() + */ + void removePath(const std::string &ipathId); + + /** + * Gets the identifiers of all paths saved in this AsyncMotionProfileController. + * + * @return The identifiers of all paths + */ + std::vector getPaths(); + + /** + * Executes a path with the given ID. If there is no path matching the ID, the method will + * return. Any targets set while a path is being followed will be ignored. + * + * @param ipathId A unique identifier for the path, previously passed to generatePath(). + */ + void setTarget(std::string ipathId) override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. This just calls setTarget(). + */ + void controllerSet(std::string ivalue) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + std::string getTarget() override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + std::string getTarget() const; + + /** + * Blocks the current task until the controller has settled. This controller is settled when + * it has finished following a path. If no path is being followed, it is settled. + */ + void waitUntilSettled() override; + + /** + * Generates a new path from the position (typically the current position) to the target and + * blocks until the controller has settled. Does not save the path which was generated. + * + * @param iposition The starting position. + * @param itarget The target position. + */ + void moveTo(double iposition, double itarget); + + /** + * Returns the last error of the controller. Does not update when disabled. Returns zero if there + * is no path currently being followed. + * + * @return the last error + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. This implementation also stops movement. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * NOT cause the controller to move to its last set target. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * NOT cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Starts the internal thread. This should not be called by normal users. This method is called + * by the AsyncControllerFactory when making a new instance of this class. + */ + void startThread(); + + protected: + struct TrajectoryPair { + Segment *segment; + int length; + }; + + Logger *logger; + std::map paths{}; + double maxVel{0}; + double maxAccel{0}; + double maxJerk{0}; + std::shared_ptr> output; + double currentProfilePosition{0}; + TimeUtil timeUtil; + + std::string currentPath{""}; + std::atomic_bool isRunning{false}; + std::atomic_bool disabled{false}; + std::atomic_bool dtorCalled{false}; + CrossplatformThread *task{nullptr}; + + static void trampoline(void *context); + void loop(); + + /** + * Follow the supplied path. Must follow the disabled lifecycle. + */ + virtual void executeSinglePath(const TrajectoryPair &path, std::unique_ptr rate); +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncMotionProfileController.hpp b/include/okapi/api/control/async/asyncMotionProfileController.hpp new file mode 100644 index 0000000..b546a75 --- /dev/null +++ b/include/okapi/api/control/async/asyncMotionProfileController.hpp @@ -0,0 +1,220 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisScales.hpp" +#include "okapi/api/chassis/model/skidSteerModel.hpp" +#include "okapi/api/control/async/asyncPositionController.hpp" +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QAngularSpeed.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/QSpeed.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include +#include + +extern "C" { +#include "okapi/pathfinder/include/pathfinder.h" +} + +namespace okapi { +struct Point { + QLength x; // X coordinate relative to the start of the movement + QLength y; // Y coordinate relative to the start of the movement + QAngle theta; // Exit angle relative to the start of the movement +}; + +class AsyncMotionProfileController : public AsyncPositionController { + public: + /** + * An Async Controller which generates and follows 2D motion profiles. Throws a + * std::invalid_argument exception if the gear ratio is zero. + * + * @param imaxVel The maximum possible velocity in m/s. + * @param imaxAccel The maximum possible acceleration in m/s/s. + * @param imaxJerk The maximum possible jerk in m/s/s/s. + * @param imodel The chassis model to control. + * @param iwidth The chassis wheelbase width. + */ + AsyncMotionProfileController(const TimeUtil &itimeUtil, + double imaxVel, + double imaxAccel, + double imaxJerk, + const std::shared_ptr &imodel, + const ChassisScales &iscales, + AbstractMotor::GearsetRatioPair ipair); + + AsyncMotionProfileController(AsyncMotionProfileController &&other) noexcept; + + ~AsyncMotionProfileController() override; + + /** + * Generates a path which intersects the given waypoints and saves it internally with a key of + * pathId. Call executePath() with the same pathId to run it. + * + * If the waypoints form a path which is impossible to achieve, an instance of std::runtime_error + * is thrown (and an error is logged) which describes the waypoints. If there are no waypoints, + * no path is generated. + * + * @param iwaypoints The waypoints to hit on the path. + * @param ipathId A unique identifier to save the path with. + */ + void generatePath(std::initializer_list iwaypoints, const std::string &ipathId); + + /** + * Removes a path and frees the memory it used. + * + * @param ipathId A unique identifier for the path, previously passed to generatePath() + */ + void removePath(const std::string &ipathId); + + /** + * Gets the identifiers of all paths saved in this AsyncMotionProfileController. + * + * @return The identifiers of all paths + */ + std::vector getPaths(); + + /** + * Executes a path with the given ID. If there is no path matching the ID, the method will + * return. Any targets set while a path is being followed will be ignored. + * + * @param ipathId A unique identifier for the path, previously passed to generatePath(). + */ + void setTarget(std::string ipathId) override; + + /** + * Executes a path with the given ID. If there is no path matching the ID, the method will + * return. Any targets set while a path is being followed will be ignored. + * + * @param ipathId A unique identifier for the path, previously passed to generatePath(). + * @param ibackwards Whether to follow the profile backwards. + */ + void setTarget(std::string ipathId, bool ibackwards); + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. This just calls setTarget(). + */ + void controllerSet(std::string ivalue) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + std::string getTarget() override; + + /** + * Blocks the current task until the controller has settled. This controller is settled when + * it has finished following a path. If no path is being followed, it is settled. + */ + void waitUntilSettled() override; + + /** + * Generates a new path from the position (typically the current position) to the target and + * blocks until the controller has settled. Does not save the path which was generated. + * + * @param iwaypoints The waypoints to hit on the path. + */ + void moveTo(std::initializer_list iwaypoints); + + /** + * Returns the last error of the controller. Does not update when disabled. This implementation + * always returns zero since the robot is assumed to perfectly follow the path. Subclasses can + * override this to be more accurate using odometry information. + * + * @return the last error + */ + Point getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Resets the controller so it can start from 0 again properly. Keeps configuration from + * before. This implementation also stops movement. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * NOT cause the controller to move to its last set target. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * NOT cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Starts the internal thread. This should not be called by normal users. This method is called + * by the AsyncControllerFactory when making a new instance of this class. + */ + void startThread(); + + protected: + struct TrajectoryPair { + Segment *left; + Segment *right; + int length; + }; + + Logger *logger; + std::map paths{}; + double maxVel{0}; + double maxAccel{0}; + double maxJerk{0}; + std::shared_ptr model; + ChassisScales scales; + AbstractMotor::GearsetRatioPair pair; + TimeUtil timeUtil; + + std::string currentPath{""}; + std::atomic_bool isRunning{false}; + std::atomic_int direction{1}; + std::atomic_bool disabled{false}; + std::atomic_bool dtorCalled{false}; + CrossplatformThread *task{nullptr}; + + static void trampoline(void *context); + void loop(); + + /** + * Follow the supplied path. Must follow the disabled lifecycle. + */ + virtual void executeSinglePath(const TrajectoryPair &path, std::unique_ptr rate); + + /** + * Converts linear chassis speed to rotational motor speed. + * + * @param linear chassis frame speed + * @return motor frame speed + */ + QAngularSpeed convertLinearToRotational(QSpeed linear) const; +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncPosIntegratedController.hpp b/include/okapi/api/control/async/asyncPosIntegratedController.hpp new file mode 100644 index 0000000..261a37c --- /dev/null +++ b/include/okapi/api/control/async/asyncPosIntegratedController.hpp @@ -0,0 +1,146 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncPositionController.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" + +namespace okapi { +/** + * Closed-loop controller that uses the V5 motor's onboard control to move. Input units are whatever + * units the motor is in. + */ +class AsyncPosIntegratedController : public AsyncPositionController { + public: + /** + * Closed-loop controller that uses the V5 motor's onboard control to move. Input units are + * whatever units the motor is in. The maximum velocity for profiled movements will be the maximum + * velocity for the motor's gearset. + * + * @param imotor the motor to control + */ + AsyncPosIntegratedController(const std::shared_ptr &imotor, + const TimeUtil &itimeUtil); + + /** + * Closed-loop controller that uses the V5 motor's onboard control to move. Input units are + * whatever units the motor is in. + * + * @param imotor the motor to control + * @param imaxVelocity the maximum velocity during a profiled movement in RPM [0-600]. + */ + AsyncPosIntegratedController(const std::shared_ptr &imotor, + std::int32_t imaxVelocity, + const TimeUtil &itimeUtil); + + /** + * Sets the target for the controller. + */ + void setTarget(double itarget) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + double getTarget() override; + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Blocks the current task until the controller has settled. Determining what settling means is + * implementation-dependent. + */ + void waitUntilSettled() override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + void controllerSet(double ivalue) override; + + /** + * Sets a new maximum velocity in RPM [0-600]. + * + * @param imaxVelocity the new maximum velocity + */ + virtual void setMaxVelocity(std::int32_t imaxVelocity); + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t tarePosition(); + + /** + * Stops the motor mid-movement. Does not change the last set target. + */ + virtual void stop(); + + protected: + Logger *logger; + std::shared_ptr motor; + std::int32_t maxVelocity{600}; // 600 RPM max, vexOS will limit if the gearset can't go this fast + double lastTarget = 0; + bool controllerIsDisabled = false; + bool hasFirstTarget = false; + std::unique_ptr settledUtil; + std::unique_ptr rate; + + /** + * Resumes moving after the controller is reset. Should not cause movement if the controller is + * turned off, reset, and turned back on. + */ + virtual void resumeMovement(); +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncPosPidController.hpp b/include/okapi/api/control/async/asyncPosPidController.hpp new file mode 100644 index 0000000..10f228a --- /dev/null +++ b/include/okapi/api/control/async/asyncPosPidController.hpp @@ -0,0 +1,32 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncPositionController.hpp" +#include "okapi/api/control/async/asyncWrapper.hpp" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/control/iterative/iterativePosPidController.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include + +namespace okapi { +class AsyncPosPIDController : public AsyncWrapper, + public AsyncPositionController { + public: + AsyncPosPIDController( + const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + const TimeUtil &itimeUtil, + double ikP, + double ikI, + double ikD, + double ikBias = 0, + std::unique_ptr iderivativeFilter = std::make_unique()); +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncPositionController.hpp b/include/okapi/api/control/async/asyncPositionController.hpp new file mode 100644 index 0000000..9897e1b --- /dev/null +++ b/include/okapi/api/control/async/asyncPositionController.hpp @@ -0,0 +1,16 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncController.hpp" +#include + +namespace okapi { +template +class AsyncPositionController : virtual public AsyncController {}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncVelIntegratedController.hpp b/include/okapi/api/control/async/asyncVelIntegratedController.hpp new file mode 100644 index 0000000..b3e9fe9 --- /dev/null +++ b/include/okapi/api/control/async/asyncVelIntegratedController.hpp @@ -0,0 +1,105 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncVelocityController.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include + +namespace okapi { +/** + * Closed-loop controller that uses the V5 motor's onboard control to move. Input units are whatever + * units the motor is in. + */ +class AsyncVelIntegratedController : public AsyncVelocityController { + public: + AsyncVelIntegratedController(const std::shared_ptr &imotor, + const TimeUtil &itimeUtil); + + /** + * Sets the target for the controller. + */ + void setTarget(double itarget) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + double getTarget() override; + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Blocks the current task until the controller has settled. Determining what settling means is + * implementation-dependent. + */ + void waitUntilSettled() override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + void controllerSet(double ivalue) override; + + protected: + Logger *logger; + std::shared_ptr motor; + double lastTarget = 0; + bool controllerIsDisabled = false; + bool hasFirstTarget = false; + std::unique_ptr settledUtil; + std::unique_ptr rate; + + virtual void resumeMovement(); +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncVelPidController.hpp b/include/okapi/api/control/async/asyncVelPidController.hpp new file mode 100644 index 0000000..f8ba01f --- /dev/null +++ b/include/okapi/api/control/async/asyncVelPidController.hpp @@ -0,0 +1,33 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncVelocityController.hpp" +#include "okapi/api/control/async/asyncWrapper.hpp" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/control/iterative/iterativeVelPidController.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include + +namespace okapi { +class AsyncVelPIDController : public AsyncWrapper, + public AsyncVelocityController { + public: + AsyncVelPIDController( + const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + const TimeUtil &itimeUtil, + double ikP, + double ikD, + double ikF, + double ikSF, + std::unique_ptr ivelMath, + std::unique_ptr iderivativeFilter = std::make_unique()); +}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncVelocityController.hpp b/include/okapi/api/control/async/asyncVelocityController.hpp new file mode 100644 index 0000000..9f598fb --- /dev/null +++ b/include/okapi/api/control/async/asyncVelocityController.hpp @@ -0,0 +1,16 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncController.hpp" +#include + +namespace okapi { +template +class AsyncVelocityController : virtual public AsyncController {}; +} // namespace okapi diff --git a/include/okapi/api/control/async/asyncWrapper.hpp b/include/okapi/api/control/async/asyncWrapper.hpp new file mode 100644 index 0000000..498ac83 --- /dev/null +++ b/include/okapi/api/control/async/asyncWrapper.hpp @@ -0,0 +1,264 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncController.hpp" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/control/iterative/iterativeController.hpp" +#include "okapi/api/control/util/settledUtil.hpp" +#include "okapi/api/coreProsAPI.hpp" +#include "okapi/api/util/abstractRate.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/mathUtil.hpp" +#include "okapi/api/util/supplier.hpp" +#include +#include + +namespace okapi { +template +class AsyncWrapper : virtual public AsyncController { + public: + /** + * A wrapper class that transforms an IterativeController into an AsyncController by running it + * in another task. The input controller will act like an AsyncController. + * + * @param iinput controller input, passed to the IterativeController + * @param ioutput controller output, written to from the IterativeController + * @param icontroller the controller to use + * @param irateSupplier used for rates used in the main loop and in waitUntilSettled + * @param isettledUtil used in waitUntilSettled + * @param iscale the scale applied to the controller output + */ + AsyncWrapper(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + std::unique_ptr> icontroller, + const Supplier> &irateSupplier) + : logger(Logger::instance()), + rateSupplier(irateSupplier), + input(iinput), + output(ioutput), + controller(std::move(icontroller)) { + } + + AsyncWrapper(AsyncWrapper &&other) noexcept + : logger(other.logger), + rateSupplier(std::move(other.rateSupplier)), + input(std::move(other.input)), + output(std::move(other.output)), + controller(std::move(other.controller)), + dtorCalled(other.dtorCalled.load(std::memory_order_acquire)), + task(other.task) { + } + + ~AsyncWrapper() override { + dtorCalled.store(true, std::memory_order_release); + delete task; + } + + /** + * Sets the target for the controller. + */ + void setTarget(Input itarget) override { + logger->info("AsyncWrapper: Set target to " + std::to_string(itarget)); + hasFirstTarget = true; + controller->setTarget(itarget); + lastTarget = itarget; + } + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. + * + * @param ivalue the controller's output + */ + void controllerSet(Input ivalue) override { + controller->controllerSet(ivalue); + } + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + Input getTarget() override { + return controller->getTarget(); + } + + /** + * Returns the last calculated output of the controller. + */ + Output getOutput() const { + return controller->getOutput(); + } + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + Output getError() const override { + return controller->getError(); + } + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override { + return isDisabled() || controller->isSettled(); + } + + /** + * Set time between loops. + * + * @param isampleTime time between loops + */ + void setSampleTime(QTime isampleTime) { + controller->setSampleTime(isampleTime); + } + + /** + * Set controller output bounds. + * + * @param imax max output + * @param imin min output + */ + void setOutputLimits(Output imax, Output imin) { + controller->setOutputLimits(imax, imin); + } + + /** + * Get the upper output bound. + * + * @return the upper output bound + */ + Output getMaxOutput() { + return controller->getMaxOutput(); + } + + /** + * Get the lower output bound. + * + * @return the lower output bound + */ + Output getMinOutput() { + return controller->getMinOutput(); + } + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override { + logger->info("AsyncWrapper: Reset"); + controller->reset(); + hasFirstTarget = false; + } + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override { + logger->info("AsyncWrapper: flipDisable " + std::to_string(!controller->isDisabled())); + controller->flipDisable(); + resumeMovement(); + } + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override { + logger->info("AsyncWrapper: flipDisable " + std::to_string(iisDisabled)); + controller->flipDisable(iisDisabled); + resumeMovement(); + } + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override { + return controller->isDisabled(); + } + + /** + * Blocks the current task until the controller has settled. Determining what settling means is + * implementation-dependent. + */ + void waitUntilSettled() override { + logger->info("AsyncWrapper: Waiting to settle"); + + auto rate = rateSupplier.get(); + while (!isSettled()) { + rate->delayUntil(motorUpdateRate); + } + + logger->info("AsyncWrapper: Done waiting to settle"); + } + + /** + * Starts the internal thread. This should not be called by normal users. This method is called + * by the AsyncControllerFactory when making a new instance of this class. + */ + void startThread() { + if (!task) { + task = new CrossplatformThread(trampoline, this); + } + } + + protected: + Logger *logger; + Supplier> rateSupplier; + std::shared_ptr> input; + std::shared_ptr> output; + std::unique_ptr> controller; + bool hasFirstTarget{false}; + Input lastTarget; + std::atomic_bool dtorCalled{false}; + CrossplatformThread *task{nullptr}; + + static void trampoline(void *context) { + if (context) { + static_cast(context)->loop(); + } + } + + void loop() { + auto rate = rateSupplier.get(); + while (!dtorCalled.load(std::memory_order_acquire)) { + if (!isDisabled()) { + output->controllerSet(controller->step(input->controllerGet())); + } + + rate->delayUntil(controller->getSampleTime()); + } + } + + /** + * Resumes moving after the controller is reset. Should not cause movement if the controller is + * turned off, reset, and turned back on. + */ + virtual void resumeMovement() { + if (isDisabled()) { + // This will grab the output *when disabled* + output->controllerSet(controller->getOutput()); + } else { + if (hasFirstTarget) { + setTarget(lastTarget); + } + } + } +}; +} // namespace okapi diff --git a/include/okapi/api/control/closedLoopController.hpp b/include/okapi/api/control/closedLoopController.hpp new file mode 100644 index 0000000..50aa87c --- /dev/null +++ b/include/okapi/api/control/closedLoopController.hpp @@ -0,0 +1,83 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/units/QTime.hpp" + +namespace okapi { +/** + * An abstract closed-loop controller. + * + * @tparam Input The target/input type. + * @tparam Output The error/output type. + */ +template +class ClosedLoopController : public ControllerOutput { + public: + virtual ~ClosedLoopController() = default; + + /** + * Sets the target for the controller. + * + * @param itarget the new target + */ + virtual void setTarget(Input itarget) = 0; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + virtual Input getTarget() = 0; + + /** + * Returns the last error of the controller. Does not update when disabled. + * + * @return the last error + */ + virtual Output getError() const = 0; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + virtual bool isSettled() = 0; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + virtual void reset() = 0; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + virtual void flipDisable() = 0; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + virtual void flipDisable(bool iisDisabled) = 0; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + virtual bool isDisabled() const = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/control/controllerInput.hpp b/include/okapi/api/control/controllerInput.hpp new file mode 100644 index 0000000..ed7141b --- /dev/null +++ b/include/okapi/api/control/controllerInput.hpp @@ -0,0 +1,21 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +namespace okapi { +template class ControllerInput { + public: + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual T controllerGet() = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/control/controllerOutput.hpp b/include/okapi/api/control/controllerOutput.hpp new file mode 100644 index 0000000..6529bc9 --- /dev/null +++ b/include/okapi/api/control/controllerOutput.hpp @@ -0,0 +1,21 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +namespace okapi { +template class ControllerOutput { + public: + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + virtual void controllerSet(T ivalue) = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativeController.hpp b/include/okapi/api/control/iterative/iterativeController.hpp new file mode 100644 index 0000000..75a2806 --- /dev/null +++ b/include/okapi/api/control/iterative/iterativeController.hpp @@ -0,0 +1,72 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/closedLoopController.hpp" +#include "okapi/api/units/QTime.hpp" + +namespace okapi { +/** + * Closed-loop controller that steps iteratively using the step method below. + * + * ControllerOutput::controllerSet() should set the controller's target to the input scaled by the + * output bounds. + */ +template +class IterativeController : public ClosedLoopController { + public: + /** + * Do one iteration of the controller. + * + * @param inewReading new measurement + * @return controller output + */ + virtual Output step(Input ireading) = 0; + + /** + * Returns the last calculated output of the controller. + */ + virtual Output getOutput() const = 0; + + /** + * Set controller output bounds. + * + * @param imax max output + * @param imin min output + */ + virtual void setOutputLimits(Output imax, Output imin) = 0; + + /** + * Get the upper output bound. + * + * @return the upper output bound + */ + virtual Output getMaxOutput() = 0; + + /** + * Get the lower output bound. + * + * @return the lower output bound + */ + virtual Output getMinOutput() = 0; + + /** + * Set time between loops. + * + * @param isampleTime time between loops + */ + virtual void setSampleTime(QTime isampleTime) = 0; + + /** + * Get the last set sample time. + * + * @return sample time + */ + virtual QTime getSampleTime() const = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativeMotorVelocityController.hpp b/include/okapi/api/control/iterative/iterativeMotorVelocityController.hpp new file mode 100644 index 0000000..82d5dd8 --- /dev/null +++ b/include/okapi/api/control/iterative/iterativeMotorVelocityController.hpp @@ -0,0 +1,138 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativeVelocityController.hpp" +#include "okapi/api/device/motor/abstractMotor.hpp" +#include +#include + +namespace okapi { +class IterativeMotorVelocityController : public IterativeVelocityController { + public: + /** + * Velocity controller that automatically writes to the motor. + */ + IterativeMotorVelocityController( + const std::shared_ptr &imotor, + const std::shared_ptr> &icontroller); + + /** + * Do one iteration of the controller. + * + * @param inewReading new measurement + * @return controller output + */ + double step(double ireading) override; + + /** + * Sets the target for the controller. + */ + void setTarget(double itarget) override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + void controllerSet(double ivalue) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + double getTarget() override; + + /** + * Returns the last calculated output of the controller. + */ + double getOutput() const override; + + /** + * Get the upper output bound. + * + * @return the upper output bound + */ + double getMaxOutput() override; + + /** + * Get the lower output bound. + * + * @return the lower output bound + */ + double getMinOutput() override; + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Set time between loops in ms. + * + * @param isampleTime time between loops in ms + */ + void setSampleTime(QTime isampleTime) override; + + /** + * Set controller output bounds. + * + * @param imax max output + * @param imin min output + */ + void setOutputLimits(double imax, double imin) override; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Get the last set sample time. + * + * @return sample time + */ + QTime getSampleTime() const override; + + protected: + std::shared_ptr motor; + std::shared_ptr> controller; +}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativePosPidController.hpp b/include/okapi/api/control/iterative/iterativePosPidController.hpp new file mode 100644 index 0000000..c0e3d36 --- /dev/null +++ b/include/okapi/api/control/iterative/iterativePosPidController.hpp @@ -0,0 +1,245 @@ +/** + * Based on the Arduino PID controller: https://github.com/br3ttb/Arduino-PID-Library + * + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativePositionController.hpp" +#include "okapi/api/control/util/settledUtil.hpp" +#include "okapi/api/filter/filter.hpp" +#include "okapi/api/filter/passthroughFilter.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include +#include + +namespace okapi { +class IterativePosPIDController : public IterativePositionController { + public: + struct Gains { + double kP{0}; + double kI{0}; + double kD{0}; + double kBias{0}; + }; + + /** + * Position PID controller. + * + * @param ikP the proportional gain + * @param ikI the integration gain + * @param ikD the derivative gain + * @param ikBias the controller bias + * @param itimeUtil see TimeUtil docs + * @param iderivativeFilter a filter for filtering the derivative term + */ + IterativePosPIDController( + double ikP, + double ikI, + double ikD, + double ikBias, + const TimeUtil &itimeUtil, + std::unique_ptr iderivativeFilter = std::make_unique()); + + /** + * Position PID controller. + * + * @param igains the controller gains + * @param itimeUtil see TimeUtil docs + * @param iderivativeFilter a filter for filtering the derivative term + */ + IterativePosPIDController( + const Gains &igains, + const TimeUtil &itimeUtil, + std::unique_ptr iderivativeFilter = std::make_unique()); + + /** + * Do one iteration of the controller. Returns the reading in the range [-1, 1] unless the + * bounds have been changed with setOutputLimits(). + * + * @param inewReading new measurement + * @return controller output + */ + double step(double inewReading) override; + + /** + * Sets the target for the controller. + * + * @param itarget new target position + */ + void setTarget(double itarget) override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + void controllerSet(double ivalue) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + double getTarget() override; + + /** + * Returns the last calculated output of the controller. Output is in the range [-1, 1] + * unless the bounds have been changed with setOutputLimits(). + */ + double getOutput() const override; + + /** + * Get the upper output bound. + * + * @return the upper output bound + */ + double getMaxOutput() override; + + /** + * Get the lower output bound. + * + * @return the lower output bound + */ + double getMinOutput() override; + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Set controller gains. + * + * @param ikP proportional gain + * @param ikI integral gain + * @param ikD derivative gain + * @param ikBias bias (constant offset added to the output) + */ + virtual void setGains(double ikP, double ikI, double ikD, double ikBias = 0); + + /** + * Set time between loops in ms. + * + * @param isampleTime time between loops + */ + void setSampleTime(QTime isampleTime) override; + + /** + * Set controller output bounds. Default bounds are [-1, 1]. + * + * @param imax max output + * @param imin min output + */ + void setOutputLimits(double imax, double imin) override; + + /** + * Set integrator bounds. Default bounds are [-1, 1]. + * + * @param imax max integrator value + * @param imin min integrator value + */ + virtual void setIntegralLimits(double imax, double imin); + + /** + * Set the error sum bounds. Default bounds are [0, std::numeric_limits::max()]. Error + * will only be added to the integral term when its absolute value is between these bounds of + * either side of the target. + * + * @param imax max error value that will be summed + * @param imin min error value that will be summed + */ + virtual void setErrorSumLimits(double imax, double imin); + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override; + + /** + * Set whether the integrator should be reset when error is 0 or changes sign. + * + * @param iresetOnZero true to reset + */ + virtual void setIntegratorReset(bool iresetOnZero); + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Get the last set sample time. + * + * @return sample time + */ + QTime getSampleTime() const override; + + protected: + Logger *logger; + double kP, kI, kD, kBias; + QTime sampleTime{10_ms}; + double target{0}; + double lastReading{0}; + double error{0}; + double lastError{0}; + std::unique_ptr derivativeFilter; + + // Integral bounds + double integral{0}; + double integralMax{1}; + double integralMin{-1}; + + // Error will only be added to the integral term within these bounds on either side of the target + double errorSumMin{0}; + double errorSumMax{std::numeric_limits::max()}; + + double derivative{0}; + + // Output bounds + double output{0}; + double outputMax{1}; + double outputMin{-1}; + + // Reset the integrated when the controller crosses 0 or not + bool shouldResetOnCross{true}; + + bool controllerIsDisabled{false}; + + std::unique_ptr loopDtTimer; + std::unique_ptr settledUtil; +}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativePositionController.hpp b/include/okapi/api/control/iterative/iterativePositionController.hpp new file mode 100644 index 0000000..f0c9187 --- /dev/null +++ b/include/okapi/api/control/iterative/iterativePositionController.hpp @@ -0,0 +1,15 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativeController.hpp" + +namespace okapi { +template +class IterativePositionController : public IterativeController {}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativeVelPidController.hpp b/include/okapi/api/control/iterative/iterativeVelPidController.hpp new file mode 100644 index 0000000..747744c --- /dev/null +++ b/include/okapi/api/control/iterative/iterativeVelPidController.hpp @@ -0,0 +1,201 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativeVelocityController.hpp" +#include "okapi/api/control/util/settledUtil.hpp" +#include "okapi/api/filter/passthroughFilter.hpp" +#include "okapi/api/filter/velMath.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" + +namespace okapi { +class IterativeVelPIDController : public IterativeVelocityController { + public: + /** + * Velocity PD controller. + * + * @param ikP the proportional gain + * @param ikD the derivative gain + * @param ikF the feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + * @param itimeUtil see TimeUtil docs + * @param iderivativeFilter a filter for filtering the derivative term + */ + IterativeVelPIDController( + double ikP, + double ikD, + double ikF, + double ikSF, + std::unique_ptr ivelMath, + const TimeUtil &itimeUtil, + std::unique_ptr iderivativeFilter = std::make_unique()); + + /** + * Do one iteration of the controller. Returns the reading in the range [-1, 1] unless the + * bounds have been changed with setOutputLimits(). + * + * @param inewReading new measurement + * @return controller output + */ + double step(double inewReading) override; + + /** + * Sets the target for the controller. + * + * @param itarget new target velocity + */ + void setTarget(double itarget) override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + void controllerSet(double ivalue) override; + + /** + * Gets the last set target, or the default target if none was set. + * + * @return the last target + */ + double getTarget() override; + + /** + * Returns the last calculated output of the controller. + */ + double getOutput() const override; + + /** + * Get the upper output bound. + * + * @return the upper output bound + */ + double getMaxOutput() override; + + /** + * Get the lower output bound. + * + * @return the lower output bound + */ + double getMinOutput() override; + + /** + * Returns the last error of the controller. Does not update when disabled. + */ + double getError() const override; + + /** + * Returns whether the controller has settled at the target. Determining what settling means is + * implementation-dependent. + * + * If the controller is disabled, this method must return true. + * + * @return whether the controller is settled + */ + bool isSettled() override; + + /** + * Set time between loops in ms. + * + * @param isampleTime time between loops + */ + void setSampleTime(QTime isampleTime) override; + + /** + * Set controller output bounds. Default bounds are [-1, 1]. + * + * @param imax max output + * @param imin min output + */ + void setOutputLimits(double imax, double imin) override; + + /** + * Resets the controller's internal state so it is similar to when it was first initialized, while + * keeping any user-configured information. + */ + void reset() override; + + /** + * Changes whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + */ + void flipDisable() override; + + /** + * Sets whether the controller is off or on. Turning the controller on after it was off will + * cause the controller to move to its last set target, unless it was reset in that time. + * + * @param iisDisabled whether the controller is disabled + */ + void flipDisable(bool iisDisabled) override; + + /** + * Returns whether the controller is currently disabled. + * + * @return whether the controller is currently disabled + */ + bool isDisabled() const override; + + /** + * Get the last set sample time. + * + * @return sample time + */ + QTime getSampleTime() const override; + + /** + * Do one iteration of velocity calculation. + * + * @param inewReading new measurement + * @return filtered velocity + */ + virtual QAngularSpeed stepVel(double inewReading); + + /** + * Set controller gains. + * + * @param ikP proportional gain + * @param ikD derivative gain + * @param ikF the feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + */ + virtual void setGains(double ikP, double ikD, double ikF, double ikSF); + + /** + * Sets the number of encoder ticks per revolution. Default is 1800. + * + * @param tpr number of measured units per revolution + */ + virtual void setTicksPerRev(double tpr); + + /** + * Returns the current velocity. + */ + virtual QAngularSpeed getVel() const; + + protected: + Logger *logger; + double kP, kD, kF, kSF; + QTime sampleTime{10_ms}; + double error{0}; + double derivative{0}; + double target{0}; + double outputSum{0}; + double output{0}; + double outputMax{1}; + double outputMin{-1}; + bool controllerIsDisabled{false}; + + std::unique_ptr velMath; + std::unique_ptr derivativeFilter; + std::unique_ptr loopDtTimer; + std::unique_ptr settledUtil; +}; +} // namespace okapi diff --git a/include/okapi/api/control/iterative/iterativeVelocityController.hpp b/include/okapi/api/control/iterative/iterativeVelocityController.hpp new file mode 100644 index 0000000..4435345 --- /dev/null +++ b/include/okapi/api/control/iterative/iterativeVelocityController.hpp @@ -0,0 +1,15 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativeController.hpp" + +namespace okapi { +template +class IterativeVelocityController : public IterativeController {}; +} // namespace okapi diff --git a/include/okapi/api/control/util/controllerRunner.hpp b/include/okapi/api/control/util/controllerRunner.hpp new file mode 100644 index 0000000..a6637d6 --- /dev/null +++ b/include/okapi/api/control/util/controllerRunner.hpp @@ -0,0 +1,125 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/async/asyncController.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/control/iterative/iterativeController.hpp" +#include "okapi/api/util/abstractRate.hpp" +#include "okapi/api/util/logging.hpp" +#include + +namespace okapi { +template class ControllerRunner { + public: + explicit ControllerRunner(std::unique_ptr irate) + : logger(Logger::instance()), rate(std::move(irate)) { + } + + /** + * Runs the controller until it has settled. + * + * @param itarget the new target + * @param icontroller the controller to run + * @return the error when settled + */ + virtual Output runUntilSettled(const Input itarget, AsyncController &icontroller) { + logger->info("ControllerRunner: runUntilSettled(AsyncController): Set target to " + + std::to_string(itarget)); + icontroller.setTarget(itarget); + + while (!icontroller.isSettled()) { + rate->delay(10); + } + + logger->info("ControllerRunner: runUntilSettled(AsyncController): Done waiting to settle"); + return icontroller.getError(); + } + + /** + * Runs the controller until it has settled. + * + * @param itarget the new target + * @param icontroller the controller to run + * @param ioutput the output to write to + * @return the error when settled + */ + virtual Output runUntilSettled(const Input itarget, + IterativeController &icontroller, + ControllerOutput &ioutput) { + logger->info("ControllerRunner: runUntilSettled(IterativeController): Set target to " + + std::to_string(itarget)); + icontroller.setTarget(itarget); + + while (!icontroller.isSettled()) { + ioutput.controllerSet(icontroller.getOutput()); + rate->delay(10); + } + + logger->info("ControllerRunner: runUntilSettled(IterativeController): Done waiting to settle"); + return icontroller.getError(); + } + + /** + * Runs the controller until it has reached its target, but not necessarily settled. + * + * @param itarget the new target + * @param icontroller the controller to run + * @return the error when settled + */ + virtual Output runUntilAtTarget(const Input itarget, + AsyncController &icontroller) { + logger->info("ControllerRunner: runUntilAtTarget(AsyncController): Set target to " + + std::to_string(itarget)); + icontroller.setTarget(itarget); + + double error = icontroller.getError(); + double lastError = error; + while (error != 0 && std::copysign(1.0, error) == std::copysign(1.0, lastError)) { + lastError = error; + rate->delay(10); + error = icontroller.getError(); + } + + logger->info("ControllerRunner: runUntilAtTarget(AsyncController): Done waiting to settle"); + return icontroller.getError(); + } + + /** + * Runs the controller until it has reached its target, but not necessarily settled. + * + * @param itarget the new target + * @param icontroller the controller to run + * @param ioutput the output to write to + * @return the error when settled + */ + virtual Output runUntilAtTarget(const Input itarget, + IterativeController &icontroller, + ControllerOutput &ioutput) { + logger->info("ControllerRunner: runUntilAtTarget(IterativeController): Set target to " + + std::to_string(itarget)); + icontroller.setTarget(itarget); + + double error = icontroller.getError(); + double lastError = error; + while (error != 0 && std::copysign(1.0, error) == std::copysign(1.0, lastError)) { + ioutput.controllerSet(icontroller.getOutput()); + lastError = error; + rate->delay(10); + error = icontroller.getError(); + } + + logger->info("ControllerRunner: runUntilAtTarget(IterativeController): Done waiting to settle"); + return icontroller.getError(); + } + + protected: + Logger *logger; + std::unique_ptr rate; +}; +} // namespace okapi diff --git a/include/okapi/api/control/util/flywheelSimulator.hpp b/include/okapi/api/control/util/flywheelSimulator.hpp new file mode 100644 index 0000000..1210cde --- /dev/null +++ b/include/okapi/api/control/util/flywheelSimulator.hpp @@ -0,0 +1,159 @@ +/** + * @author Kevin Harrington, Common Wealth Robotics + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include + +namespace okapi { +class FlywheelSimulator { + public: + /** + * A simulator for an inverted pendulum. The center of mass of the system changes as the link + * rotates (by default, you can set a new torque function with setExternalTorqueFunction()). + */ + explicit FlywheelSimulator(double imass = 0.01, + double ilinkLen = 1, + double imuStatic = 0.1, + double imuDynamic = 0.9, + double itimestep = 0.01); + + virtual ~FlywheelSimulator(); + + /** + * Step the simulation by the timestep. + * + * @return the current angle + */ + double step(); + + /** + * Step the simulation by the timestep. + * + * @param itorque new input torque + * @return the current angle + */ + double step(double itorque); + + /** + * Sets the torque function used to calculate the torque due to external forces. This torque gets + * summed with the input torque. + * + * For example, the default torque function has the torque due to gravity vary as the link swings: + * [](double angle, double mass, double linkLength) { + * return (linkLength * std::cos(angle)) * (mass * -1 * gravity); + * } + * + * @param itorqueFunc the torque function. The return value is the torque due to external forces + */ + void setExternalTorqueFunction( + std::function itorqueFunc); + + /** + * Sets the input torque. The input will be bounded by the max torque. + * + * @param itorque new input torque + */ + void setTorque(double itorque); + + /** + * Sets the max torque. The input torque cannot exceed this maximum torque. + * + * @param imaxTorque new maximum torque + */ + void setMaxTorque(double imaxTorque); + + /** + * Sets the current angle. + * + * @param iangle new angle + **/ + void setAngle(double iangle); + + /** + * Sets the mass (kg). + * + * @param imass new mass + */ + void setMass(double imass); + + /** + * Sets the link length (m). + * + * @param ilinkLen new link length + */ + void setLinkLength(double ilinkLen); + + /** + * Sets the static friction (N*m). + * + * @param imuStatic new static friction + */ + void setStaticFriction(double imuStatic); + + /** + * Sets the dynamic friction (N*m). + * + * @param imuDynamic new dynamic friction + */ + void setDynamicFriction(double imuDynamic); + + /** + * Sets the timestep (sec). + * + * @param itimestep new timestep + */ + void setTimestep(double itimestep); + + /** + * Returns the current angle (angle in rad). + * + * @return the current angle + */ + double getAngle() const; + + /** + * Returns the current omgea (angular velocity in rad / sec). + * + * @return the current omega + */ + double getOmega() const; + + /** + * Returns the current acceleration (angular acceleration in rad / sec^2). + * + * @return the current acceleration + */ + double getAcceleration() const; + + /** + * Returns the maximum torque input. + * + * @return the max torque input + */ + double getMaxTorque() const; + + protected: + double inputTorque = 0; // N*m + double maxTorque = 0.5649; // N*m + double angle = 0; // rad + double omega = 0; // rad / sec + double accel = 0; // rad / sec^2 + double mass; // kg + double linkLen; // m + double muStatic; // N*m + double muDynamic; // N*m + double timestep; // sec + double I = 0; // moment of inertia + std::function torqueFunc; + + const double minTimestep = 0.000001; // 1 us + + virtual double stepImpl(); +}; +} // namespace okapi diff --git a/include/okapi/api/control/util/pidTuner.hpp b/include/okapi/api/control/util/pidTuner.hpp new file mode 100644 index 0000000..4befca2 --- /dev/null +++ b/include/okapi/api/control/util/pidTuner.hpp @@ -0,0 +1,83 @@ +/** + * @author Jonathan Bayless, Team BLRS + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/control/iterative/iterativePosPidController.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/util/logging.hpp" +#include "okapi/api/util/timeUtil.hpp" +#include +#include + +namespace okapi { +class PIDTuner { + public: + struct Output { + double kP, kI, kD; + }; + + PIDTuner(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + const TimeUtil &itimeUtil, + QTime itimeout, + std::int32_t igoal, + double ikPMin, + double ikPMax, + double ikIMin, + double ikIMax, + double ikDMin, + double ikDMax, + std::size_t inumIterations = 5, + std::size_t inumParticles = 16, + double ikSettle = 1, + double ikITAE = 2); + + virtual ~PIDTuner(); + + virtual Output autotune(); + + protected: + static constexpr double inertia = 0.5; // Particle inertia + static constexpr double confSelf = 1.1; // Self confidence + static constexpr double confSwarm = 1.2; // Particle swarm confidence + static constexpr int increment = 5; + static constexpr int divisor = 5; + static constexpr QTime loopDelta = 10_ms; // NOLINT + + struct Particle { + double pos, vel, best; + }; + + struct ParticleSet { + Particle kP, kI, kD; + double bestError; + }; + + Logger *logger; + std::shared_ptr> input; + std::shared_ptr> output; + TimeUtil timeUtil; + std::unique_ptr rate; + + const QTime timeout; + const std::int32_t goal; + const double kPMin; + const double kPMax; + const double kIMin; + const double kIMax; + const double kDMin; + const double kDMax; + const std::size_t numIterations; + const std::size_t numParticles; + const double kSettle; + const double kITAE; +}; +} // namespace okapi diff --git a/include/okapi/api/control/util/settledUtil.hpp b/include/okapi/api/control/util/settledUtil.hpp new file mode 100644 index 0000000..be52893 --- /dev/null +++ b/include/okapi/api/control/util/settledUtil.hpp @@ -0,0 +1,52 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/util/abstractTimer.hpp" +#include + +namespace okapi { +class SettledUtil { + public: + /** + * A utility class to determine if a control loop has settled based on error. A control loop is + * settled if the error is within atTargetError and atTargetDerivative for atTargetTime. + * + * @param iatTargetError minimum error to be considered settled + * @param iatTargetDerivative minimum error derivative to be considered settled + * @param iatTargetTime minimum time within atTargetError to be considered settled + */ + explicit SettledUtil(std::unique_ptr iatTargetTimer, + double iatTargetError = 50, + double iatTargetDerivative = 5, + QTime iatTargetTime = 250_ms); + + virtual ~SettledUtil(); + + /** + * Returns whether the controller is settled. + * + * @param ierror current error + * @return whether the controller is settled + */ + virtual bool isSettled(double ierror); + + /** + * Resets the "at target" timer. + */ + virtual void reset(); + + protected: + double atTargetError = 50; + double atTargetDerivative = 5; + QTime atTargetTime = 250_ms; + std::unique_ptr atTargetTimer; + double lastError = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/coreProsAPI.hpp b/include/okapi/api/coreProsAPI.hpp new file mode 100644 index 0000000..9585316 --- /dev/null +++ b/include/okapi/api/coreProsAPI.hpp @@ -0,0 +1,52 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#ifdef THREADS_STD +#include +#define CROSSPLATFORM_THREAD_T std::thread +#else +#include "api.h" +#define CROSSPLATFORM_THREAD_T pros::task_t +#endif + +class CrossplatformThread { + public: + CrossplatformThread(void (*ptr)(void *), void *params) + : +#ifdef THREADS_STD + thread(ptr, params) +#else + thread(pros::c::task_create(ptr, + params, + TASK_PRIORITY_DEFAULT, + TASK_STACK_DEPTH_DEFAULT, + "OkapiLibCrossplatformTask")) +#endif + { + } + + ~CrossplatformThread() { +#ifdef THREADS_STD + thread.join(); +#else + pros::c::task_delete(thread); +#endif + } + + protected: + CROSSPLATFORM_THREAD_T thread; +}; diff --git a/include/okapi/api/device/button/abstractButton.hpp b/include/okapi/api/device/button/abstractButton.hpp new file mode 100644 index 0000000..4619016 --- /dev/null +++ b/include/okapi/api/device/button/abstractButton.hpp @@ -0,0 +1,48 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerInput.hpp" + +namespace okapi { +class AbstractButton : public ControllerInput { + public: + virtual ~AbstractButton(); + + /** + * Return whether the button is currently pressed. + **/ + virtual bool isPressed() = 0; + + /** + * Return whether the state of the button changed since the last time this method was + * called. + **/ + virtual bool changed() = 0; + + /** + * Return whether the state of the button changed to being pressed since the last time this method + * was called. + **/ + virtual bool changedToPressed() = 0; + + /** + * Return whether the state of the button to being not pressed changed since the last time this + * method was called. + **/ + virtual bool changedToReleased() = 0; + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value. This is the same as the output of the pressed() method. + */ + virtual bool controllerGet() override; +}; +} // namespace okapi diff --git a/include/okapi/api/device/button/buttonBase.hpp b/include/okapi/api/device/button/buttonBase.hpp new file mode 100644 index 0000000..21ff972 --- /dev/null +++ b/include/okapi/api/device/button/buttonBase.hpp @@ -0,0 +1,50 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/device/button/abstractButton.hpp" + +namespace okapi { +class ButtonBase : public AbstractButton { + public: + explicit ButtonBase(bool iinverted = false); + + /** + * Return whether the button is currently pressed. + **/ + bool isPressed() override; + + /** + * Return whether the state of the button changed since the last time this method was called. + **/ + bool changed() override; + + /** + * Return whether the state of the button changed to pressed since the last time this method was + *called. + **/ + bool changedToPressed() override; + + /** + * Return whether the state of the button to not pressed since the last time this method was + *called. + **/ + bool changedToReleased() override; + + protected: + bool inverted{false}; + bool wasPressedLast_c{false}; + bool wasPressedLast_ctp{false}; + bool wasPressedLast_ctr{false}; + + virtual bool currentlyPressed() = 0; + + private: + bool changedImpl(bool &prevState); +}; +} // namespace okapi diff --git a/include/okapi/api/device/motor/abstractMotor.hpp b/include/okapi/api/device/motor/abstractMotor.hpp new file mode 100644 index 0000000..e5abe01 --- /dev/null +++ b/include/okapi/api/device/motor/abstractMotor.hpp @@ -0,0 +1,576 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerOutput.hpp" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" +#include + +namespace okapi { +class AbstractMotor : public ControllerOutput { + public: + /** + * Indicates the 'brake mode' of a motor. + */ + enum class brakeMode { + coast = 0, // Motor coasts when stopped, traditional behavior + brake = 1, // Motor brakes when stopped + hold = 2, // Motor actively holds position when stopped + invalid = INT32_MAX + }; + + /** + * Indicates the units used by the motor encoders. + */ + enum class encoderUnits { degrees = 0, rotations = 1, counts = 2, invalid = INT32_MAX }; + + /** + * Indicates the internal gear ratio of a motor. + */ + enum class gearset { + red = 100, // 36:1, 100 RPM, Red gear set + green = 200, // 18:1, 200 RPM, Green gear set + blue = 600, // 6:1, 600 RPM, Blue gear set + invalid = INT32_MAX + }; + + /** + * A simple structure representing the full ratio between motor and wheel. + */ + struct GearsetRatioPair { + /** + * A simple structure representing the full ratio between motor and wheel. + * + * The ratio is motor rotation : wheel rotation. So for example, if one motor rotation + * corresponds to two wheel rotations, the ratio is 1.0/2.0. + * + * @param igearset the motor's gearset + * @param iratio the ratio of motor rotation to wheel rotation + */ + GearsetRatioPair(const gearset igearset, const double iratio = 1) + : internalGearset(igearset), ratio(iratio) { + } + + ~GearsetRatioPair() = default; + + const gearset internalGearset; + const double ratio = 1; + }; + + virtual ~AbstractMotor(); + + /******************************************************************************/ + /** Motor movement functions **/ + /** **/ + /** These functions allow programmers to make motors move **/ + /******************************************************************************/ + + /** + * Sets the target absolute position for the motor to move to. + * + * This movement is relative to the position of the motor when initialized or + * the position when it was most recently reset with setZeroPosition(). + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The absolute position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveAbsolute(double iposition, std::int32_t ivelocity) = 0; + + /** + * Sets the relative target position for the motor to move to. + * + * This movement is relative to the current position of the motor. Providing 10.0 as the position + * parameter would result in the motor moving clockwise 10 units, no matter what the current + * position is. + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The relative position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveRelative(double iposition, std::int32_t ivelocity) = 0; + + /** + * Sets the velocity for the motor. + * + * This velocity corresponds to different actual speeds depending on the gearset + * used for the motor. This results in a range of +-100 for pros::c::red, + * +-200 for green, and +-600 for blue. The velocity + * is held with PID to ensure consistent speed, as opposed to setting the motor's + * voltage. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVelocity(std::int16_t ivelocity) = 0; + + /** + * Sets the voltage for the motor from -12000 to 12000. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivoltage The new voltage value from -12000 to 12000 + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVoltage(std::int16_t ivoltage) = 0; + + /** + * Changes the output velocity for a profiled movement (moveAbsolute or moveRelative). This will + * have no effect if the motor is not following a profiled movement. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t modifyProfiledVelocity(std::int32_t ivelocity) = 0; + + /******************************************************************************/ + /** Motor telemetry functions **/ + /** **/ + /** These functions allow programmers to collect telemetry from motors **/ + /******************************************************************************/ + + /** + * Gets the target position set for the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The target position in its encoder units or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTargetPosition() = 0; + + /** + * Gets the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's absolute position in its encoder units or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double getPosition() = 0; + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t tarePosition() = 0; + + /** + * Gets the velocity commanded to the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The commanded motor velocity from +-100, +-200, or +-600, or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t getTargetVelocity() = 0; + + /** + * Gets the actual velocity of the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's actual velocity in RPM or PROS_ERR_F if the operation failed, setting + * errno. + */ + virtual double getActualVelocity() = 0; + + /** + * Gets the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentDraw() = 0; + + /** + * Gets the direction of movement for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 for moving in the positive direction, -1 for moving in the negative direction, and + * PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getDirection() = 0; + + /** + * Gets the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's efficiency in percent or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getEfficiency() = 0; + + /** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the motor's current limit is being exceeded and 0 if the current limit is not + * exceeded, or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverCurrent() = 0; + + /** + * Checks if the motor's temperature is above its limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the temperature limit is exceeded and 0 if the the temperature is below the limit, + * or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverTemp() = 0; + + /** + * Checks if the motor is stopped. + * + * Although this function forwards data from the motor, the motor presently does not provide any + * value. This function returns PROS_ERR with errno set to ENOSYS. + * + * @return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR if the operation + * failed, setting errno + */ + virtual std::int32_t isStopped() = 0; + + /** + * Checks if the motor is at its zero position. + * + * Although this function forwards data from the motor, the motor presently does not provide any + * value. This function returns PROS_ERR with errno set to ENOSYS. + * + * @return 1 if the motor is at zero absolute position, 0 if the motor has moved from its absolute + * zero, or PROS_ERR if the operation failed, setting errno + */ + virtual std::int32_t getZeroPositionFlag() = 0; + + /** + * Gets the faults experienced by the motor. Compare this bitfield to the bitmasks in + * pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's faults. 0b00000100 = Current Limit + * Hit + */ + virtual uint32_t getFaults() = 0; + + /** + * Gets the flags set by the motor's operation. Compare this bitfield to the bitmasks in + * pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's flags. These seem to be unrelated + * to the individual get_specific_flag functions + */ + virtual uint32_t getFlags() = 0; + + /** + * Gets the raw encoder count of the motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param timestamp A pointer to a time in milliseconds for which the encoder count will be + * returned. If NULL, the timestamp at which the encoder count was read will not be supplied + * + * @return The raw encoder count at the given timestamp or PROS_ERR if the operation failed. + */ + virtual std::int32_t getRawPosition(std::uint32_t *timestamp) = 0; + + /** + * Gets the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's power draw in Watts or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getPower() = 0; + + /** + * Gets the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's temperature in degrees Celsius or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTemperature() = 0; + + /** + * Gets the torque generated by the motor in Newton Metres (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's torque in NM or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getTorque() = 0; + + /** + * Gets the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's voltage in V or PROS_ERR_F if the operation failed, setting errno. + */ + virtual std::int32_t getVoltage() = 0; + + /******************************************************************************/ + /** Motor configuration functions **/ + /** **/ + /** These functions allow programmers to configure the behavior of motors **/ + /******************************************************************************/ + + /** + * Sets one of brakeMode to the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param imode The new motor brake mode to set for the motor + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setBrakeMode(brakeMode imode) = 0; + + /** + * Gets the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of brakeMode, according to what was set for the motor, or brakeMode::invalid if the + * operation failed, setting errno. + */ + virtual brakeMode getBrakeMode() = 0; + + /** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new current limit in mA + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setCurrentLimit(std::int32_t ilimit) = 0; + + /** + * Gets the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current limit in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentLimit() = 0; + + /** + * Sets one of encoderUnits for the motor encoder. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iunits The new motor encoder units + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setEncoderUnits(encoderUnits iunits) = 0; + + /** + * Gets the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of encoderUnits according to what is set for the motor or encoderUnits::invalid if + * the operation failed. + */ + virtual encoderUnits getEncoderUnits() = 0; + + /** + * Sets one of gearset for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param igearset The new motor gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setGearing(gearset igearset) = 0; + + /** + * Gets the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of gearset according to what is set for the motor, or gearset::invalid if the + * operation failed. + */ + virtual gearset getGearing() = 0; + + /** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ireverse True reverses the motor, false is default + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setReversed(bool ireverse) = 0; + + /** + * Sets the voltage limit for the motor in Volts. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new voltage limit in Volts + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVoltageLimit(std::int32_t ilimit) = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPID(double ikF, double ikP, double ikI, double ikD) = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPID(double ikF, double ikP, double ikI, double ikD) = 0; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) = 0; + + /** + * Returns the encoder associated with this motor. + * + * @return the encoder for this motor + */ + virtual std::shared_ptr getEncoder() = 0; +}; + +AbstractMotor::GearsetRatioPair operator*(AbstractMotor::gearset gearset, double ratio); + +} // namespace okapi diff --git a/include/okapi/api/device/rotarysensor/continuousRotarySensor.hpp b/include/okapi/api/device/rotarysensor/continuousRotarySensor.hpp new file mode 100644 index 0000000..7899331 --- /dev/null +++ b/include/okapi/api/device/rotarysensor/continuousRotarySensor.hpp @@ -0,0 +1,22 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/device/rotarysensor/rotarySensor.hpp" + +namespace okapi { +class ContinuousRotarySensor : public RotarySensor { + public: + /** + * Reset the sensor to zero. + * + * @return 1 on success, PROS_ERR on fail + */ + virtual std::int32_t reset() = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/device/rotarysensor/rotarySensor.hpp b/include/okapi/api/device/rotarysensor/rotarySensor.hpp new file mode 100644 index 0000000..7bce55d --- /dev/null +++ b/include/okapi/api/device/rotarysensor/rotarySensor.hpp @@ -0,0 +1,25 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/coreProsAPI.hpp" + +namespace okapi { +class RotarySensor : public ControllerInput { + public: + virtual ~RotarySensor(); + + /** + * Get the current sensor value. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double get() const = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/averageFilter.hpp b/include/okapi/api/filter/averageFilter.hpp new file mode 100644 index 0000000..fb26f39 --- /dev/null +++ b/include/okapi/api/filter/averageFilter.hpp @@ -0,0 +1,61 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" +#include +#include + +namespace okapi { +/** + * A filter which returns the average of a list of values. + * + * @tparam n number of taps in the filter + */ +template class AverageFilter : public Filter { + public: + /** + * Averaging filter. + */ + AverageFilter() = default; + + /** + * Filters a value, like a sensor reading. + * + * @param ireading new measurement + * @return filtered result + */ + double filter(const double ireading) override { + data[index++] = ireading; + if (index >= n) { + index = 0; + } + + output = 0.0; + for (size_t i = 0; i < n; i++) + output += data[i]; + output /= (double)n; + + return output; + } + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override { + return output; + } + + protected: + std::array data{0}; + std::size_t index = 0; + double output = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/composableFilter.hpp b/include/okapi/api/filter/composableFilter.hpp new file mode 100644 index 0000000..cafd39b --- /dev/null +++ b/include/okapi/api/filter/composableFilter.hpp @@ -0,0 +1,61 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" +#include +#include +#include +#include + +namespace okapi { +class ComposableFilter : public Filter { + public: + /** + * A composable filter is a filter that consists of other filters. The input signal is passed + * through each filter in sequence. The final output of this filter is the output of the last + * filter. + */ + ComposableFilter(); + + /** + * A composable filter is a filter that consists of other filters. The input signal is passed + * through each filter in sequence. The final output of this filter is the output of the last + * filter. + * + * @param ilist the filters to use in sequence + */ + ComposableFilter(const std::initializer_list> &ilist); + + /** + * Filters a value, like a sensor reading. + * + * @param ireading new measurement + * @return filtered result + */ + double filter(double ireading) override; + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override; + + /** + * Adds a filter to the end of the sequence. + * + * @param ifilter the filter to add + */ + virtual void addFilter(const std::shared_ptr &ifilter); + + protected: + std::vector> filters; + double output = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/demaFilter.hpp b/include/okapi/api/filter/demaFilter.hpp new file mode 100644 index 0000000..f3469fa --- /dev/null +++ b/include/okapi/api/filter/demaFilter.hpp @@ -0,0 +1,54 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" +#include + +namespace okapi { +class DemaFilter : public Filter { + public: + /** + * Double exponential moving average filter. + * + * @param ialpha alpha gain + * @param ibeta beta gain + */ + DemaFilter(double ialpha, double ibeta); + + /** + * Filters a value, like a sensor reading. + * + * @param reading new measurement + * @return filtered result + */ + double filter(double ireading) override; + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override; + + /** + * Set filter gains. + * + * @param ialpha alpha gain + * @param ibeta beta gain + */ + virtual void setGains(double ialpha, double ibeta); + + protected: + double alpha, beta; + double outputS = 0; + double lastOutputS = 0; + double outputB = 0; + double lastOutputB = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/ekfFilter.hpp b/include/okapi/api/filter/ekfFilter.hpp new file mode 100644 index 0000000..143d540 --- /dev/null +++ b/include/okapi/api/filter/ekfFilter.hpp @@ -0,0 +1,73 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" +#include "okapi/api/util/mathUtil.hpp" + +namespace okapi { +class EKFFilter : public Filter { + public: + /** + * One dimensional extended Kalman filter. The default arguments should work fine for most signal + * filtering. It won't hurt to graph your signal and the filtered result, and check if the filter + * is doing its job. + * + * Q is the covariance of the process noise and R is the + * covariance of the observation noise. The default values for Q and R should be a modest balance + * between trust in the sensor and FIR filtering. + * + * Think of R as how noisy your sensor is. Its value can be found mathematically by computing the + * standard deviation of your sensor reading vs. "truth" (of course, "truth" is still an estimate; + * try to calibrate your robot in a controlled setting where you can minimize the error in what + * "truth" is). + * + * Think of Q as how noisy your model is. It decides how much "smoothing" the filter does and how + * far it lags behind the true signal. This parameter is most often used as a "tuning" parameter + * to adjust the response of the filter. + * + * @param iQ process noise covariance + * @param iR measurement noise covariance + */ + explicit EKFFilter(double iQ = 0.0001, double iR = ipow(0.2, 2)); + + /** + * Filters a value, like a sensor reading. Assumes the control input is zero. + * + * @param ireading new measurement + * @return filtered result + */ + double filter(double ireading) override; + + /** + * Filters a reading with a control input. + * + * @param ireading new measurement + * @param icontrol control input + * @return filtered result + */ + virtual double filter(double ireading, double icontrol); + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override; + + protected: + const double Q, R; + double xHat = 0; + double xHatPrev = 0; + double xHatMinus = 0; + double P = 0; + double Pprev = 1; + double Pminus = 0; + double K = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/emaFilter.hpp b/include/okapi/api/filter/emaFilter.hpp new file mode 100644 index 0000000..1e72ff7 --- /dev/null +++ b/include/okapi/api/filter/emaFilter.hpp @@ -0,0 +1,49 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" + +namespace okapi { +class EmaFilter : public Filter { + public: + /** + * Exponential moving average filter. + * + * @param ialpha alpha gain + */ + explicit EmaFilter(double ialpha); + + /** + * Filters a value, like a sensor reading. + * + * @param reading new measurement + * @return filtered result + */ + double filter(double ireading) override; + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override; + + /** + * Set filter gains. + * + * @param ialpha alpha gain + */ + virtual void setGains(double ialpha); + + protected: + double alpha; + double output = 0; + double lastOutput = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/filter.hpp b/include/okapi/api/filter/filter.hpp new file mode 100644 index 0000000..65cfa97 --- /dev/null +++ b/include/okapi/api/filter/filter.hpp @@ -0,0 +1,30 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +namespace okapi { +class Filter { + public: + virtual ~Filter(); + + /** + * Filters a value, like a sensor reading. + * + * @param ireading new measurement + * @return filtered result + */ + virtual double filter(double ireading) = 0; + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + virtual double getOutput() const = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/filteredControllerInput.hpp b/include/okapi/api/filter/filteredControllerInput.hpp new file mode 100644 index 0000000..07f9b4c --- /dev/null +++ b/include/okapi/api/filter/filteredControllerInput.hpp @@ -0,0 +1,50 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/filter/filter.hpp" +#include + +namespace okapi { +/** + * A ControllerInput with a filter built in. + * + * @tparam InputType the type of the ControllerInput + * @tparam FilterType the type of the Filter + */ +template +class FilteredControllerInput : public ControllerInput { + public: + /** + * A filtered controller input. Applies a filter to the controller input. Useful if you want to + * place a filter between a control input and a control loop. + * + * @param iinput ControllerInput type + * @param ifilter Filter type + */ + FilteredControllerInput(std::unique_ptr> iinput, + std::unique_ptr ifilter) + : input(std::move(iinput)), filter(std::move(ifilter)) { + } + + /** + * Gets the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current filtered sensor value. + */ + double controllerGet() override { + return filter->filter(input->controllerGet()); + } + + protected: + std::unique_ptr> input; + std::unique_ptr filter; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/medianFilter.hpp b/include/okapi/api/filter/medianFilter.hpp new file mode 100644 index 0000000..5d24993 --- /dev/null +++ b/include/okapi/api/filter/medianFilter.hpp @@ -0,0 +1,96 @@ +/** + * Uses the median filter algorithm from N. Wirth’s book, implementation by N. Devillard. + * + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" +#include +#include +#include + +namespace okapi { +/** + * A filter which returns the median value of list of values. + * + * @tparam n number of taps in the filter + */ +template class MedianFilter : public Filter { + public: + MedianFilter() : middleIndex((((n)&1) ? ((n) / 2) : (((n) / 2) - 1))) { + } + + /** + * Filters a value, like a sensor reading. + * + * @param ireading new measurement + * @return filtered result + */ + double filter(const double ireading) override { + data[index++] = ireading; + if (index >= n) { + index = 0; + } + + output = kth_smallset(); + return output; + } + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override { + return output; + } + + protected: + std::array data{0}; + std::size_t index = 0; + double output = 0; + const size_t middleIndex; + + /** + * Algorithm from N. Wirth’s book, implementation by N. Devillard. + */ + double kth_smallset() { + std::array dataCopy = data; + size_t j, l, m; + l = 0; + m = n - 1; + + while (l < m) { + double x = dataCopy[middleIndex]; + size_t i = l; + j = m; + do { + while (dataCopy[i] < x) { + i++; + } + while (x < dataCopy[j]) { + j--; + } + if (i <= j) { + const double t = dataCopy[i]; + dataCopy[i] = dataCopy[j]; + dataCopy[j] = t; + i++; + j--; + } + } while (i <= j); + if (j < middleIndex) + l = i; + if (middleIndex < i) + m = j; + } + + return dataCopy[middleIndex]; + } +}; +} // namespace okapi diff --git a/include/okapi/api/filter/passthroughFilter.hpp b/include/okapi/api/filter/passthroughFilter.hpp new file mode 100644 index 0000000..6965324 --- /dev/null +++ b/include/okapi/api/filter/passthroughFilter.hpp @@ -0,0 +1,38 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/filter.hpp" + +namespace okapi { +class PassthroughFilter : public Filter { + public: + /** + * A simple filter that does no filtering and just passes the input through. + */ + PassthroughFilter(); + + /** + * Filters a value, like a sensor reading. + * + * @param ireading new measurement + * @return filtered result + */ + double filter(double ireading) override; + + /** + * Returns the previous output from filter. + * + * @return the previous output from filter + */ + double getOutput() const override; + + protected: + double lastOutput = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/filter/velMath.hpp b/include/okapi/api/filter/velMath.hpp new file mode 100644 index 0000000..1b63271 --- /dev/null +++ b/include/okapi/api/filter/velMath.hpp @@ -0,0 +1,89 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/composableFilter.hpp" +#include "okapi/api/units/QAngularAcceleration.hpp" +#include "okapi/api/units/QAngularSpeed.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/util/abstractTimer.hpp" +#include "okapi/api/util/logging.hpp" +#include + +namespace okapi { +class VelMathArgs { + public: + explicit VelMathArgs(double iticksPerRev, QTime isampleTime = 0_ms); + VelMathArgs(double iticksPerRev, + const std::shared_ptr &ifilter, + QTime isampleTime = 0_ms); + + virtual ~VelMathArgs(); + + double ticksPerRev; + std::shared_ptr filter; + QTime sampleTime; +}; + +class VelMath { + public: + /** + * Velocity math helper. Calculates filtered velocity. Throws a std::invalid_argument exception + * if iticksPerRev is zero. + * + * @param iticksPerRev number of ticks per revolution (or whatever units you are using) + * @param ifilter filter used for filtering the calculated velocity + * @param isampleTime the minimum time between velocity measurements + */ + VelMath(double iticksPerRev, + const std::shared_ptr &ifilter, + QTime isampleTime, + std::unique_ptr iloopDtTimer); + + VelMath(const VelMathArgs &iparams, std::unique_ptr iloopDtTimer); + + virtual ~VelMath(); + + /** + * Calculates the current velocity and acceleration. Returns the (filtered) velocity. + * + * @param inewPos new position + * @return current (filtered) velocity + */ + virtual QAngularSpeed step(double inewPos); + + /** + * Sets ticks per revolution (or whatever units you are using). + * + * @para iTPR ticks per revolution + */ + virtual void setTicksPerRev(double iTPR); + + /** + * Returns the last calculated velocity. + */ + virtual QAngularSpeed getVelocity() const; + + /** + * Returns the last calculated acceleration. + */ + virtual QAngularAcceleration getAccel() const; + + protected: + Logger *logger; + QAngularSpeed vel; + QAngularSpeed lastVel; + QAngularAcceleration accel; + double lastPos = 0; + double ticksPerRev; + + QTime sampleTime; + std::unique_ptr loopDtTimer; + std::shared_ptr filter; +}; +} // namespace okapi diff --git a/include/okapi/api/units/QAcceleration.hpp b/include/okapi/api/units/QAcceleration.hpp new file mode 100644 index 0000000..4d7fb70 --- /dev/null +++ b/include/okapi/api/units/QAcceleration.hpp @@ -0,0 +1,40 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 1, -2, 0, QAcceleration) + +constexpr QAcceleration mps2 = meter / (second * second); +constexpr QAcceleration G = 9.80665 * mps2; + +inline namespace literals { +constexpr QAcceleration operator"" _mps2(long double x) { + return QAcceleration(x); +} +constexpr QAcceleration operator"" _mps2(unsigned long long int x) { + return QAcceleration(static_cast(x)); +} +constexpr QAcceleration operator"" _G(long double x) { + return static_cast(x) * G; +} +constexpr QAcceleration operator"" _G(unsigned long long int x) { + return static_cast(x) * G; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QAngle.hpp b/include/okapi/api/units/QAngle.hpp new file mode 100644 index 0000000..c2615d5 --- /dev/null +++ b/include/okapi/api/units/QAngle.hpp @@ -0,0 +1,39 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" +#include + +namespace okapi { +QUANTITY_TYPE(0, 0, 0, 1, QAngle) + +constexpr QAngle radian(1.0); +constexpr QAngle degree = static_cast(2_pi / 360.0) * radian; + +inline namespace literals { +constexpr QAngle operator"" _rad(long double x) { + return QAngle(x); +} +constexpr QAngle operator"" _rad(unsigned long long int x) { + return QAngle(static_cast(x)); +} +constexpr QAngle operator"" _deg(long double x) { + return static_cast(x) * degree; +} +constexpr QAngle operator"" _deg(unsigned long long int x) { + return static_cast(x) * degree; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QAngularAcceleration.hpp b/include/okapi/api/units/QAngularAcceleration.hpp new file mode 100644 index 0000000..8440e8b --- /dev/null +++ b/include/okapi/api/units/QAngularAcceleration.hpp @@ -0,0 +1,20 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 0, -2, 1, QAngularAcceleration) +} diff --git a/include/okapi/api/units/QAngularJerk.hpp b/include/okapi/api/units/QAngularJerk.hpp new file mode 100644 index 0000000..a43fe3f --- /dev/null +++ b/include/okapi/api/units/QAngularJerk.hpp @@ -0,0 +1,20 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 0, -3, 1, QAngularJerk) +} diff --git a/include/okapi/api/units/QAngularSpeed.hpp b/include/okapi/api/units/QAngularSpeed.hpp new file mode 100644 index 0000000..2070c0e --- /dev/null +++ b/include/okapi/api/units/QAngularSpeed.hpp @@ -0,0 +1,34 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QAngle.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 0, -1, 1, QAngularSpeed) + +constexpr QAngularSpeed radps = radian / second; +constexpr QAngularSpeed rpm = (360 * degree) / minute; + +inline namespace literals { +constexpr QAngularSpeed operator"" _rpm(long double x) { + return x * rpm; +} +constexpr QAngularSpeed operator"" _rpm(unsigned long long int x) { + return static_cast(x) * rpm; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QArea.hpp b/include/okapi/api/units/QArea.hpp new file mode 100644 index 0000000..0df2ebe --- /dev/null +++ b/include/okapi/api/units/QArea.hpp @@ -0,0 +1,30 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 2, 0, 0, QArea) + +constexpr QArea kilometer2 = kilometer * kilometer; +constexpr QArea meter2 = meter * meter; +constexpr QArea decimeter2 = decimeter * decimeter; +constexpr QArea centimeter2 = centimeter * centimeter; +constexpr QArea millimeter2 = millimeter * millimeter; +constexpr QArea inch2 = inch * inch; +constexpr QArea foot2 = foot * foot; +constexpr QArea mile2 = mile * mile; +} // namespace okapi diff --git a/include/okapi/api/units/QForce.hpp b/include/okapi/api/units/QForce.hpp new file mode 100644 index 0000000..9ddbe57 --- /dev/null +++ b/include/okapi/api/units/QForce.hpp @@ -0,0 +1,47 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QAcceleration.hpp" +#include "okapi/api/units/QMass.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(1, 1, -2, 0, QForce) + +constexpr QForce newton = (kg * meter) / (second * second); +constexpr QForce poundforce = pound * G; +constexpr QForce kilopond = kg * G; + +inline namespace literals { +constexpr QForce operator"" _n(long double x) { + return QForce(x); +} +constexpr QForce operator"" _n(unsigned long long int x) { + return QForce(static_cast(x)); +} +constexpr QForce operator"" _lbf(long double x) { + return static_cast(x) * poundforce; +} +constexpr QForce operator"" _lbf(unsigned long long int x) { + return static_cast(x) * poundforce; +} +constexpr QForce operator"" _kp(long double x) { + return static_cast(x) * kilopond; +} +constexpr QForce operator"" _kp(unsigned long long int x) { + return static_cast(x) * kilopond; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QFrequency.hpp b/include/okapi/api/units/QFrequency.hpp new file mode 100644 index 0000000..f85bcdf --- /dev/null +++ b/include/okapi/api/units/QFrequency.hpp @@ -0,0 +1,31 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 0, -1, 0, QFrequency) + +constexpr QFrequency Hz(1.0); + +inline namespace literals { +constexpr QFrequency operator"" _Hz(long double x) { + return QFrequency(x); +} +constexpr QFrequency operator"" _Hz(unsigned long long int x) { + return QFrequency(static_cast(x)); +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QJerk.hpp b/include/okapi/api/units/QJerk.hpp new file mode 100644 index 0000000..8bd8631 --- /dev/null +++ b/include/okapi/api/units/QJerk.hpp @@ -0,0 +1,22 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 1, -3, 0, QJerk) +} diff --git a/include/okapi/api/units/QLength.hpp b/include/okapi/api/units/QLength.hpp new file mode 100644 index 0000000..8d9ce5f --- /dev/null +++ b/include/okapi/api/units/QLength.hpp @@ -0,0 +1,81 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 1, 0, 0, QLength) + +constexpr QLength meter(1.0); // SI base unit +constexpr QLength decimeter = meter / 10; +constexpr QLength centimeter = meter / 100; +constexpr QLength millimeter = meter / 1000; +constexpr QLength kilometer = 1000 * meter; +constexpr QLength inch = 2.54 * centimeter; +constexpr QLength foot = 12 * inch; +constexpr QLength yard = 3 * foot; +constexpr QLength mile = 5280 * foot; + +inline namespace literals { +constexpr QLength operator"" _mm(long double x) { + return static_cast(x) * millimeter; +} +constexpr QLength operator"" _cm(long double x) { + return static_cast(x) * centimeter; +} +constexpr QLength operator"" _m(long double x) { + return static_cast(x) * meter; +} +constexpr QLength operator"" _km(long double x) { + return static_cast(x) * kilometer; +} +constexpr QLength operator"" _mi(long double x) { + return static_cast(x) * mile; +} +constexpr QLength operator"" _yd(long double x) { + return static_cast(x) * yard; +} +constexpr QLength operator"" _ft(long double x) { + return static_cast(x) * foot; +} +constexpr QLength operator"" _in(long double x) { + return static_cast(x) * inch; +} +constexpr QLength operator"" _mm(unsigned long long int x) { + return static_cast(x) * millimeter; +} +constexpr QLength operator"" _cm(unsigned long long int x) { + return static_cast(x) * centimeter; +} +constexpr QLength operator"" _m(unsigned long long int x) { + return static_cast(x) * meter; +} +constexpr QLength operator"" _km(unsigned long long int x) { + return static_cast(x) * kilometer; +} +constexpr QLength operator"" _mi(unsigned long long int x) { + return static_cast(x) * mile; +} +constexpr QLength operator"" _yd(unsigned long long int x) { + return static_cast(x) * yard; +} +constexpr QLength operator"" _ft(unsigned long long int x) { + return static_cast(x) * foot; +} +constexpr QLength operator"" _in(unsigned long long int x) { + return static_cast(x) * inch; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QMass.hpp b/include/okapi/api/units/QMass.hpp new file mode 100644 index 0000000..5f9fb1a --- /dev/null +++ b/include/okapi/api/units/QMass.hpp @@ -0,0 +1,66 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(1, 0, 0, 0, QMass) + +constexpr QMass kg(1.0); // SI base unit +constexpr QMass gramme = 0.001 * kg; +constexpr QMass tonne = 1000 * kg; +constexpr QMass ounce = 0.028349523125 * kg; +constexpr QMass pound = 16 * ounce; +constexpr QMass stone = 14 * pound; + +inline namespace literals { +constexpr QMass operator"" _kg(long double x) { + return QMass(x); +} +constexpr QMass operator"" _g(long double x) { + return static_cast(x) * gramme; +} +constexpr QMass operator"" _t(long double x) { + return static_cast(x) * tonne; +} +constexpr QMass operator"" _oz(long double x) { + return static_cast(x) * ounce; +} +constexpr QMass operator"" _lb(long double x) { + return static_cast(x) * pound; +} +constexpr QMass operator"" _st(long double x) { + return static_cast(x) * stone; +} +constexpr QMass operator"" _kg(unsigned long long int x) { + return QMass(static_cast(x)); +} +constexpr QMass operator"" _g(unsigned long long int x) { + return static_cast(x) * gramme; +} +constexpr QMass operator"" _t(unsigned long long int x) { + return static_cast(x) * tonne; +} +constexpr QMass operator"" _oz(unsigned long long int x) { + return static_cast(x) * ounce; +} +constexpr QMass operator"" _lb(unsigned long long int x) { + return static_cast(x) * pound; +} +constexpr QMass operator"" _st(unsigned long long int x) { + return static_cast(x) * stone; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QPressure.hpp b/include/okapi/api/units/QPressure.hpp new file mode 100644 index 0000000..a5a11ff --- /dev/null +++ b/include/okapi/api/units/QPressure.hpp @@ -0,0 +1,48 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QAcceleration.hpp" +#include "okapi/api/units/QArea.hpp" +#include "okapi/api/units/QMass.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(1, -1, -2, 0, QPressure) + +constexpr QPressure pascal(1.0); +constexpr QPressure bar = 100000 * pascal; +constexpr QPressure psi = pound * G / inch2; + +inline namespace literals { +constexpr QPressure operator"" _Pa(long double x) { + return QPressure(x); +} +constexpr QPressure operator"" _Pa(unsigned long long int x) { + return QPressure(static_cast(x)); +} +constexpr QPressure operator"" _bar(long double x) { + return static_cast(x) * bar; +} +constexpr QPressure operator"" _bar(unsigned long long int x) { + return static_cast(x) * bar; +} +constexpr QPressure operator"" _psi(long double x) { + return static_cast(x) * psi; +} +constexpr QPressure operator"" _psi(unsigned long long int x) { + return static_cast(x) * psi; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QSpeed.hpp b/include/okapi/api/units/QSpeed.hpp new file mode 100644 index 0000000..f598193 --- /dev/null +++ b/include/okapi/api/units/QSpeed.hpp @@ -0,0 +1,47 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/QTime.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 1, -1, 0, QSpeed) + +constexpr QSpeed mps = meter / second; +constexpr QSpeed miph = mile / hour; +constexpr QSpeed kmph = kilometer / hour; + +inline namespace literals { +constexpr QSpeed operator"" _mps(long double x) { + return static_cast(x) * mps; +} +constexpr QSpeed operator"" _miph(long double x) { + return static_cast(x) * mile / hour; +} +constexpr QSpeed operator"" _kmph(long double x) { + return static_cast(x) * kilometer / hour; +} +constexpr QSpeed operator"" _mps(unsigned long long int x) { + return static_cast(x) * mps; +} +constexpr QSpeed operator"" _miph(unsigned long long int x) { + return static_cast(x) * mile / hour; +} +constexpr QSpeed operator"" _kmph(unsigned long long int x) { + return static_cast(x) * kilometer / hour; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QTime.hpp b/include/okapi/api/units/QTime.hpp new file mode 100644 index 0000000..1efd254 --- /dev/null +++ b/include/okapi/api/units/QTime.hpp @@ -0,0 +1,59 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 0, 1, 0, QTime) + +constexpr QTime second(1.0); // SI base unit +constexpr QTime millisecond = second / 1000; +constexpr QTime minute = 60 * second; +constexpr QTime hour = 60 * minute; +constexpr QTime day = 24 * hour; + +inline namespace literals { +constexpr QTime operator"" _s(long double x) { + return QTime(x); +} +constexpr QTime operator"" _ms(long double x) { + return static_cast(x) * millisecond; +} +constexpr QTime operator"" _min(long double x) { + return static_cast(x) * minute; +} +constexpr QTime operator"" _h(long double x) { + return static_cast(x) * hour; +} +constexpr QTime operator"" _day(long double x) { + return static_cast(x) * day; +} +constexpr QTime operator"" _s(unsigned long long int x) { + return QTime(static_cast(x)); +} +constexpr QTime operator"" _ms(unsigned long long int x) { + return static_cast(x) * millisecond; +} +constexpr QTime operator"" _min(unsigned long long int x) { + return static_cast(x) * minute; +} +constexpr QTime operator"" _h(unsigned long long int x) { + return static_cast(x) * hour; +} +constexpr QTime operator"" _day(unsigned long long int x) { + return static_cast(x) * day; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QTorque.hpp b/include/okapi/api/units/QTorque.hpp new file mode 100644 index 0000000..99e1491 --- /dev/null +++ b/include/okapi/api/units/QTorque.hpp @@ -0,0 +1,47 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QForce.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(1, 2, -2, 0, QTorque) + +constexpr QTorque newtonMeter = newton * meter; +constexpr QTorque footPound = 1.355817948 * newtonMeter; +constexpr QTorque inchPound = 0.083333333 * footPound; + +inline namespace literals { +constexpr QTorque operator"" _nM(long double x) { + return QTorque(x); +} +constexpr QTorque operator"" _nM(unsigned long long int x) { + return QTorque(static_cast(x)); +} +constexpr QTorque operator"" _inLb(long double x) { + return static_cast(x) * inchPound; +} +constexpr QTorque operator"" _inLb(unsigned long long int x) { + return static_cast(x) * inchPound; +} +constexpr QTorque operator"" _ftLb(long double x) { + return static_cast(x) * footPound; +} +constexpr QTorque operator"" _ftLb(unsigned long long int x) { + return static_cast(x) * footPound; +} +} // namespace literals +} // namespace okapi diff --git a/include/okapi/api/units/QVolume.hpp b/include/okapi/api/units/QVolume.hpp new file mode 100644 index 0000000..ba509e8 --- /dev/null +++ b/include/okapi/api/units/QVolume.hpp @@ -0,0 +1,32 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QArea.hpp" +#include "okapi/api/units/QLength.hpp" +#include "okapi/api/units/RQuantity.hpp" + +namespace okapi { +QUANTITY_TYPE(0, 3, 0, 0, QVolume) + +constexpr QVolume kilometer3 = kilometer2 * kilometer; +constexpr QVolume meter3 = meter2 * meter; +constexpr QVolume decimeter3 = decimeter2 * decimeter; +constexpr QVolume centimeter3 = centimeter2 * centimeter; +constexpr QVolume millimeter3 = millimeter2 * millimeter; +constexpr QVolume inch3 = inch2 * inch; +constexpr QVolume foot3 = foot2 * foot; +constexpr QVolume mile3 = mile2 * mile; +constexpr QVolume litre = decimeter3; +} // namespace okapi diff --git a/include/okapi/api/units/RQuantity.hpp b/include/okapi/api/units/RQuantity.hpp new file mode 100644 index 0000000..8505e0b --- /dev/null +++ b/include/okapi/api/units/RQuantity.hpp @@ -0,0 +1,179 @@ +/** + * @author Mikhail Semenov + * @author Benjamin Jurke + * @author Ryan Benasutti, WPI + * + * This code is a modified version of Benjamin Jurke's work in 2015. You can read his blog post + * here: + * https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include + +namespace okapi { +template +class RQuantity { + public: + explicit constexpr RQuantity() : value(0.0) { + } + + explicit constexpr RQuantity(double val) : value(val) { + } + + explicit constexpr RQuantity(long double val) : value(static_cast(val)) { + } + + // The intrinsic operations for a quantity with a unit is addition and subtraction + constexpr RQuantity const &operator+=(const RQuantity &rhs) { + value += rhs.value; + return *this; + } + + constexpr RQuantity const &operator-=(const RQuantity &rhs) { + value -= rhs.value; + return *this; + } + + constexpr RQuantity operator-() { + return RQuantity(value * -1); + } + + // Returns the value of the quantity in multiples of the specified unit + constexpr double convert(const RQuantity &rhs) const { + return value / rhs.value; + } + + // returns the raw value of the quantity (should not be used) + constexpr double getValue() const { + return value; + } + + private: + double value; +}; + +// Predefined (physical unit) quantity types: +// ------------------------------------------ +#define QUANTITY_TYPE(_Mdim, _Ldim, _Tdim, _Adim, name) \ + typedef RQuantity, std::ratio<_Ldim>, std::ratio<_Tdim>, std::ratio<_Adim>> \ + name; + +// Unitless +QUANTITY_TYPE(0, 0, 0, 0, Number) + +// Standard arithmetic operators: +// ------------------------------ +template +constexpr RQuantity operator+(const RQuantity &lhs, + const RQuantity &rhs) { + return RQuantity(lhs.getValue() + rhs.getValue()); +} +template +constexpr RQuantity operator-(const RQuantity &lhs, + const RQuantity &rhs) { + return RQuantity(lhs.getValue() - rhs.getValue()); +} +template +constexpr RQuantity, + std::ratio_add, + std::ratio_add, + std::ratio_add> +operator*(const RQuantity &lhs, const RQuantity &rhs) { + return RQuantity, + std::ratio_add, + std::ratio_add, + std::ratio_add>(lhs.getValue() * rhs.getValue()); +} +template +constexpr RQuantity operator*(const double &lhs, const RQuantity &rhs) { + return RQuantity(lhs * rhs.getValue()); +} +template +constexpr RQuantity operator*(const RQuantity &lhs, const double &rhs) { + return RQuantity(lhs.getValue() * rhs); +} +template +constexpr RQuantity, + std::ratio_subtract, + std::ratio_subtract, + std::ratio_subtract> +operator/(const RQuantity &lhs, const RQuantity &rhs) { + return RQuantity, + std::ratio_subtract, + std::ratio_subtract, + std::ratio_subtract>(lhs.getValue() / rhs.getValue()); +} +template +constexpr RQuantity, M>, + std::ratio_subtract, L>, + std::ratio_subtract, T>, + std::ratio_subtract, A>> +operator/(const double &x, const RQuantity &rhs) { + return RQuantity, M>, + std::ratio_subtract, L>, + std::ratio_subtract, T>, + std::ratio_subtract, A>>(x / rhs.getValue()); +} +template +constexpr RQuantity operator/(const RQuantity &rhs, const double &x) { + return RQuantity(rhs.getValue() / x); +} + +// Comparison operators for quantities: +// ------------------------------------ +template +constexpr bool operator==(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() == rhs.getValue()); +} +template +constexpr bool operator!=(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() != rhs.getValue()); +} +template +constexpr bool operator<=(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() <= rhs.getValue()); +} +template +constexpr bool operator>=(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() >= rhs.getValue()); +} +template +constexpr bool operator<(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() < rhs.getValue()); +} +template +constexpr bool operator>(const RQuantity &lhs, const RQuantity &rhs) { + return (lhs.getValue() > rhs.getValue()); +} + +inline namespace literals { +constexpr long double operator"" _pi(long double x) { + return static_cast(x) * 3.1415926535897932384626433832795; +} +constexpr long double operator"" _pi(unsigned long long int x) { + return static_cast(x) * 3.1415926535897932384626433832795; +} +} // namespace literals +} // namespace okapi + +// Conversion macro, which utilizes the string literals +#define ConvertTo(_x, _y) (_x).convert(1.0_##_y) diff --git a/include/okapi/api/util/abstractRate.hpp b/include/okapi/api/util/abstractRate.hpp new file mode 100644 index 0000000..e06f44e --- /dev/null +++ b/include/okapi/api/util/abstractRate.hpp @@ -0,0 +1,51 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/coreProsAPI.hpp" +#include "okapi/api/units/QFrequency.hpp" +#include "okapi/api/units/QTime.hpp" + +namespace okapi { +class AbstractRate { + public: + virtual ~AbstractRate(); + + /** + * Delay the current task such that it runs at the given frequency. The first delay will run for + * 1000/(ihz). Subsequent delays will adjust according to the previous runtime of the task. + * + * @param ihz the frequency + */ + virtual void delay(QFrequency ihz) = 0; + + /** + * Delay the current task such that it runs every ihz ms. The first delay will run for + * 1000/(ihz). Subsequent delays will adjust according to the previous runtime of the task. + * + * @param ihz the frequency in ms + */ + virtual void delay(int ihz) = 0; + + /** + * Delay the current task until itime has passed. This method can be used by periodic tasks to + * ensure a consistent execution frequency. + * + * @param itime the time period + */ + virtual void delayUntil(QTime itime) = 0; + + /** + * Delay the current task until ims milliseconds have passed. This method can be used by + * periodic tasks to ensure a consistent execution frequency. + * + * @param ims the time period + */ + virtual void delayUntil(uint32_t ims) = 0; +}; +} // namespace okapi diff --git a/include/okapi/api/util/abstractTimer.hpp b/include/okapi/api/util/abstractTimer.hpp new file mode 100644 index 0000000..cb8b5ed --- /dev/null +++ b/include/okapi/api/util/abstractTimer.hpp @@ -0,0 +1,127 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/units/QFrequency.hpp" +#include "okapi/api/units/QTime.hpp" + +namespace okapi { +class AbstractTimer { + public: + /** + * A Timer base class which implements its methods in terms of millis(). + * + * @param ifirstCalled the current time + */ + explicit AbstractTimer(QTime ifirstCalled); + + virtual ~AbstractTimer(); + + /** + * Returns the current time in units of QTime. + * + * @return the current time + */ + virtual QTime millis() const = 0; + + /** + * Returns the time passed in ms since the previous call of this function. + * + * @return The time passed in ms since the previous call of this function + */ + virtual QTime getDt(); + + /** + * Returns the time passed in ms since the previous call of getDt(). Does not change the time + * recorded by getDt(). + * + * @return The time passed in ms since the previous call of getDt() + */ + virtual QTime readDt() const; + + /** + * Returns the time the timer was first constructed. + * + * @return The time the timer was first constructed + */ + virtual QTime getStartingTime() const; + + /** + * Returns the time since the timer was first constructed. + * + * @return The time since the timer was first constructed + */ + virtual QTime getDtFromStart() const; + + /** + * Place a time marker. Placing another marker will overwrite the previous one. + */ + virtual void placeMark(); + + /** + * Clears the marker. + * + * @return The old marker + */ + virtual QTime clearMark(); + + /** + * Place a hard time marker. Placing another hard marker will not overwrite the previous one; + * instead, call clearHardMark() and then place another. + */ + virtual void placeHardMark(); + + /** + * Clears the hard marker. + * + * @return The old hard marker + */ + virtual QTime clearHardMark(); + + /** + * Returns the time since the time marker. Returns 0_ms if there is no marker. + * + * @return The time since the time marker + */ + virtual QTime getDtFromMark() const; + + /** + * Returns the time since the hard time marker. Returns 0_ms if there is no hard marker set. + * + * @return The time since the hard time marker + */ + virtual QTime getDtFromHardMark() const; + + /** + * Returns true when the input time period has passed, then resets. Meant to be used in loops + * to run an action every time period without blocking. + * + * @param time time period + * @return true when the input time period has passed, false after reading true until the + * period has passed again + */ + virtual bool repeat(QTime time); + + /** + * Returns true when the input time period has passed, then resets. Meant to be used in loops + * to run an action every time period without blocking. + * + * @param frequency the repeat frequency + * @return true when the input time period has passed, false after reading true until the + * period has passed again + */ + virtual bool repeat(QFrequency frequency); + + protected: + QTime firstCalled; + QTime lastCalled; + QTime mark; + QTime hardMark; + QTime repeatMark; +}; +} // namespace okapi diff --git a/include/okapi/api/util/logging.hpp b/include/okapi/api/util/logging.hpp new file mode 100644 index 0000000..b2638ac --- /dev/null +++ b/include/okapi/api/util/logging.hpp @@ -0,0 +1,73 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/util/abstractTimer.hpp" +#include + +namespace okapi { +class Logger { + public: + enum class LogLevel { off = 0, debug = 4, info = 3, warn = 2, error = 1 }; + + /** + * Initializes the logger. If the logger is not initialized when logging methods are called, + * nothing will be logged. + * + * @param itimer A timer used to get the current time for log statements. + * @param logfileName The name of the log file to open. + * @param level The log level. Log statements above this level will be disabled. + */ + static void initialize(std::unique_ptr itimer, + std::string_view filename, + LogLevel level) noexcept; + + /** + * Initializes the logger. If the logger is not initialized when logging methods are called, + * nothing will be logged. + * + * @param itimer A timer used to get the current time for log statements. + * @param logfileName The name of the log file to open. + * @param level The log level. Log statements above this level will be disabled. + */ + static void + initialize(std::unique_ptr itimer, FILE *file, LogLevel level) noexcept; + + /** + * Get the logger instance. + */ + static Logger *instance() noexcept; + + /** + * Set a new logging level. Log statements above this level will be disabled. For example, if the + * level is set to LogLevel::warn, then LogLevel::warn and LogLevel::error will be enabled, but + * LogLevel::info and LogLevel::debug will be disabled. + */ + static void setLogLevel(LogLevel level) noexcept; + + void debug(std::string_view message) const noexcept; + + void info(std::string_view message) const noexcept; + + void warn(std::string_view message) const noexcept; + + void error(std::string_view message) const noexcept; + + /** + * Closes the connection to the log file. + */ + void close() noexcept; + + private: + Logger(); + static Logger *s_instance; + static std::unique_ptr timer; + static LogLevel logLevel; + static FILE *logfile; +}; +} // namespace okapi diff --git a/include/okapi/api/util/mathUtil.hpp b/include/okapi/api/util/mathUtil.hpp new file mode 100644 index 0000000..1cea334 --- /dev/null +++ b/include/okapi/api/util/mathUtil.hpp @@ -0,0 +1,124 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include + +namespace okapi { +static constexpr double analogInToV = 286.0; +static constexpr double inchToMM = 25.4; +static constexpr double mmToInch = 0.0393700787; +static constexpr double degreeToRadian = 0.01745; +static constexpr double radianToDegree = 57.2957795; +static constexpr double imeTorqueTPR = 627.2; +static constexpr double imeSpeedTPR = 392.0; +static constexpr double imeTurboTPR = 261.333; +static constexpr double ime269TPR = 240.448; +static constexpr double imev5TPR = 1800.0; +static constexpr double quadEncoderTPR = 360.0; +static constexpr double pi = 3.1415926535897932; +static constexpr double pi2 = 1.5707963267948966; +static constexpr double gravity = 9.80665; + +static constexpr std::int8_t motorUpdateRate = 10; +static constexpr std::int8_t adiUpdateRate = 10; + +/** + * Integer power function. Computes base^expo. + * + * @param base base + * @param expo exponent + * @return base^expo + */ +constexpr double ipow(const double base, const int expo) { + return (expo == 0) + ? 1 + : expo == 1 ? base + : expo > 1 ? ((expo & 1) ? base * ipow(base, expo - 1) + : ipow(base, expo / 2) * ipow(base, expo / 2)) + : 1 / ipow(base, -expo); +} + +/** + * Cuts out a range from the number. The new range of the input number will be + * (-inf, min]U[max, +inf). If value sits equally between min and max, max will be returned. + * + * @param value number to bound + * @param min lower bound of range + * @param max upper bound of range + * @return the remapped value + */ +constexpr double cutRange(const double value, const double min, const double max) { + const double middle = max - ((max - min) / 2); + + if (value > min && value < middle) { + return min; + } else if (value <= max && value >= middle) { + return max; + } + + return value; +} + +/** + * Deadbands a range of the number. Returns the input value, or 0 if it is in the range [min, max]. + * + * @param value number to deadband + * @param min lower bound of deadband + * @param max upper bound of deadband + * @return value, or 0 if it is in the range [min, max] + */ +constexpr double deadband(const double value, const double min, const double max) { + return std::clamp(value, min, max) == value ? 0 : value; +} + +/** + * Remap a value in the range [oldMin, oldMax] to the range [newMin, newMax]. + * + * @param value value in the old range + * @param oldMin old range lower bound + * @param oldMax old range upper bound + * @param newMin new range lower bound + * @param newMax new range upper bound + * @return remapped value in the new range [newMin, newMax] + */ +constexpr double remapRange(const double value, + const double oldMin, + const double oldMax, + const double newMin, + const double newMax) { + return (value - oldMin) * ((newMax - newMin) / (oldMax - oldMin)) + newMin; +} + +/** + * Converts an enum to its value type. + */ +template constexpr auto toUnderlyingType(const E e) noexcept { + return static_cast>(e); +} + +/** + * Converts a bool to a sign. True corresponds to 1 and false corresponds to -1. + */ +constexpr auto boolToSign(const bool b) noexcept { + return b ? 1 : -1; +} + +/** + * Computes lhs mod rhs using Euclidean division. C's % symbol computes the remainder, not modulus. + * + * @param lhs the left-hand side + * @param rhs the right-hand side + * @return lhs mod rhs + */ +constexpr long modulus(const long lhs, const long rhs) noexcept { + return ((lhs % rhs) + rhs) % rhs; +} +} // namespace okapi diff --git a/include/okapi/api/util/supplier.hpp b/include/okapi/api/util/supplier.hpp new file mode 100644 index 0000000..512b814 --- /dev/null +++ b/include/okapi/api/util/supplier.hpp @@ -0,0 +1,36 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include + +namespace okapi { +/** + * A supplier of instances of T. + * + * @tparam T the type to supply + */ +template class Supplier { + public: + explicit Supplier(std::function ifunc) : func(ifunc) { + } + + virtual ~Supplier() = default; + + /** + * Get an instance of type T. This is usually a new instance, but it does not have to be. + * @return an instance of T + */ + T get() const { + return func(); + } + + protected: + std::function func; +}; +} // namespace okapi diff --git a/include/okapi/api/util/timeUtil.hpp b/include/okapi/api/util/timeUtil.hpp new file mode 100644 index 0000000..634a9b6 --- /dev/null +++ b/include/okapi/api/util/timeUtil.hpp @@ -0,0 +1,43 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/util/settledUtil.hpp" +#include "okapi/api/util/abstractRate.hpp" +#include "okapi/api/util/abstractTimer.hpp" +#include "okapi/api/util/supplier.hpp" + +namespace okapi { +/** + * Utility class for holding an AbstractTimer, AbstractRate, and SettledUtil together in one + * class since they are commonly used together. + */ +class TimeUtil { + public: + TimeUtil(const Supplier> &itimerSupplier, + const Supplier> &irateSupplier, + const Supplier> &isettledUtilSupplier); + + std::unique_ptr getTimer() const; + + std::unique_ptr getRate() const; + + std::unique_ptr getSettledUtil() const; + + const Supplier> getTimerSupplier() const; + + const Supplier> getRateSupplier() const; + + const Supplier> getSettledUtilSupplier() const; + + protected: + Supplier> timerSupplier; + Supplier> rateSupplier; + Supplier> settledUtilSupplier; +}; +} // namespace okapi diff --git a/include/okapi/impl/chassis/controller/chassisControllerFactory.hpp b/include/okapi/impl/chassis/controller/chassisControllerFactory.hpp new file mode 100644 index 0000000..1be9e81 --- /dev/null +++ b/include/okapi/impl/chassis/controller/chassisControllerFactory.hpp @@ -0,0 +1,232 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisControllerIntegrated.hpp" +#include "okapi/api/chassis/controller/chassisControllerPid.hpp" +#include "okapi/api/chassis/model/skidSteerModel.hpp" +#include "okapi/api/chassis/model/xDriveModel.hpp" +#include "okapi/api/util/mathUtil.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include "okapi/impl/device/motor/motorGroup.hpp" +#include "okapi/impl/device/rotarysensor/adiEncoder.hpp" +#include "okapi/impl/device/rotarysensor/integratedEncoder.hpp" +#include "okapi/impl/util/timeUtilFactory.hpp" + +#define okapi_makeCreateEndParams \ + AbstractMotor::GearsetRatioPair igearset = AbstractMotor::gearset::red, \ + const ChassisScales &iscales = ChassisScales({1, 1}), \ + const TimeUtil &itimeUtil = TimeUtilFactory::create() + +#define okapi_makeCreateEndBody igearset, iscales, itimeUtil + +#define okapi_tankParams(MotorType) MotorType ileftMtr, MotorType irightMtr + +#define okapi_tankBody(MotorType) \ + std::make_shared(ileftMtr), std::make_shared(irightMtr) + +#define okapi_tankSensorBody ileftMtr.getEncoder(), irightMtr.getEncoder() + +#define okapi_xdriveParams(MotorType) \ + MotorType itopLeftMtr, MotorType itopRightMtr, MotorType ibottomRightMtr, MotorType ibottomLeftMtr + +#define okapi_xdriveBody(MotorType) \ + std::make_shared(itopLeftMtr), std::make_shared(itopRightMtr), \ + std::make_shared(ibottomRightMtr), std::make_shared(ibottomLeftMtr) + +#define okapi_xdriveSensorBody itopLeftMtr.getEncoder(), itopRightMtr.getEncoder() + +#define okapi_makeCreateIntImpl(driveType, motorType, methodName) \ + static auto methodName(okapi_##driveType##Params(motorType), okapi_makeCreateEndParams) { \ + return methodName( \ + okapi_##driveType##Body(motorType), okapi_##driveType##SensorBody, okapi_makeCreateEndBody); \ + } + +#define okapi_makeCreateIntImpl2(motorType, methodName) \ + okapi_makeCreateIntImpl(tank, motorType, methodName); \ + okapi_makeCreateIntImpl(xdrive, motorType, methodName) + +#define okapi_makeCreateInt(motorType) \ + okapi_makeCreateIntImpl2(motorType, create); \ + okapi_makeCreateIntImpl2(motorType, createPtr) + +#define okapi_pidGains2Params() \ + const IterativePosPIDController::Gains &idistanceGains, \ + const IterativePosPIDController::Gains &iangleGains + +#define okapi_pidGains2Body() \ + std::make_unique(idistanceGains, TimeUtilFactory::create()), \ + std::make_unique(iangleGains, TimeUtilFactory::create()), \ + std::make_unique(iangleGains, TimeUtilFactory::create()) + +#define okapi_pidGains3Params() \ + const IterativePosPIDController::Gains &idistanceGains, \ + const IterativePosPIDController::Gains &iangleGains, \ + const IterativePosPIDController::Gains &iturnGains + +#define okapi_pidGains3Body() \ + std::make_unique(idistanceGains, TimeUtilFactory::create()), \ + std::make_unique(iangleGains, TimeUtilFactory::create()), \ + std::make_unique(iturnGains, TimeUtilFactory::create()) + +#define okapi_makeCreatePidImpl(driveType, pidGainsType, motorType, methodName) \ + static auto methodName(okapi_##driveType##Params(motorType), \ + okapi_##pidGainsType##Params(), \ + okapi_makeCreateEndParams) { \ + return methodName(okapi_##driveType##Body(motorType), \ + okapi_##driveType##SensorBody, \ + okapi_##pidGainsType##Body(), \ + okapi_makeCreateEndBody); \ + } + +#define okapi_makeCreatePidImpl2(pidGainsType, motorType, methodName) \ + okapi_makeCreatePidImpl(tank, pidGainsType, motorType, methodName); \ + okapi_makeCreatePidImpl(xdrive, pidGainsType, motorType, methodName) + +#define okapi_makeCreatePidImpl3(motorType, methodName) \ + okapi_makeCreatePidImpl2(pidGains2, motorType, methodName); \ + okapi_makeCreatePidImpl2(pidGains3, motorType, methodName) + +#define okapi_makeCreatePid(motorType) \ + okapi_makeCreatePidImpl3(motorType, create); \ + okapi_makeCreatePidImpl3(motorType, createPtr) + +#define okapi_sensorParams(SensorType) const SensorType &ileftSens, const SensorType &irightSens + +#define okapi_sensorBody(SensorType) \ + std::make_shared(ileftSens), std::make_shared(irightSens) + +#define okapi_makeCreatePidWithSensorImpl( \ + driveType, sensorType, pidGainsType, motorType, methodName) \ + static auto methodName(okapi_##driveType##Params(motorType), \ + okapi_sensorParams(sensorType), \ + okapi_##pidGainsType##Params(), \ + okapi_makeCreateEndParams) { \ + return methodName(okapi_##driveType##Body(motorType), \ + okapi_sensorBody(sensorType), \ + okapi_##pidGainsType##Body(), \ + okapi_makeCreateEndBody); \ + } + +#define okapi_makeCreatePidWithSensorImpl2(sensorType, pidGainsType, motorType, methodName) \ + okapi_makeCreatePidWithSensorImpl(tank, sensorType, pidGainsType, motorType, methodName); \ + okapi_makeCreatePidWithSensorImpl(xdrive, sensorType, pidGainsType, motorType, methodName) + +#define okapi_makeCreatePidWithSensorImpl3(pidGainsType, motorType, methodName) \ + okapi_makeCreatePidWithSensorImpl2(IntegratedEncoder, pidGainsType, motorType, methodName); \ + okapi_makeCreatePidWithSensorImpl2(ADIEncoder, pidGainsType, motorType, methodName) + +#define okapi_makeCreatePidWithSensorImpl4(motorType, methodName) \ + okapi_makeCreatePidWithSensorImpl3(pidGains2, motorType, methodName); \ + okapi_makeCreatePidWithSensorImpl3(pidGains3, motorType, methodName) + +#define okapi_makeCreatePidWithSensor(motorType) \ + okapi_makeCreatePidWithSensorImpl4(motorType, create); \ + okapi_makeCreatePidWithSensorImpl4(motorType, createPtr) + +#define okapi_makeCreateAll(motorType) \ + okapi_makeCreateInt(motorType); \ + okapi_makeCreatePid(motorType); \ + okapi_makeCreatePidWithSensor(motorType) + +#define okapi_baseTankParams \ + const std::shared_ptr &ileftMtr, const std::shared_ptr &irightMtr + +#define okapi_baseTankBody ileftMtr, irightMtr + +#define okapi_baseTankControllerBody \ + std::make_unique(ileftMtr, TimeUtilFactory::create()), \ + std::make_unique(irightMtr, TimeUtilFactory::create()) + +#define okapi_baseXdriveParams \ + const std::shared_ptr &itopLeftMtr, \ + const std::shared_ptr &itopRightMtr, \ + const std::shared_ptr &ibottomRightMtr, \ + const std::shared_ptr &ibottomLeftMtr + +#define okapi_baseXdriveBody itopLeftMtr, itopRightMtr, ibottomRightMtr, ibottomLeftMtr + +#define okapi_baseXdriveControllerBody \ + std::make_unique(itopLeftMtr, TimeUtilFactory::create()), \ + std::make_unique(itopRightMtr, TimeUtilFactory::create()) + +#define okapi_baseSensorParams \ + const std::shared_ptr &ileftSensor, \ + const std::shared_ptr &irightSensor + +#define okapi_baseSensorBody ileftSensor, irightSensor + +#define okapi_makeCreateBaseIntImpl( \ + returnType, allocateExpr, methodName, modelType, fullModelTypeName) \ + static returnType methodName( \ + okapi_##modelType##Params, okapi_baseSensorParams, okapi_makeCreateEndParams) { \ + return allocateExpr( \ + itimeUtil, \ + std::make_shared(okapi_##modelType##Body, \ + okapi_baseSensorBody, \ + toUnderlyingType(igearset.internalGearset)), \ + okapi_##modelType##ControllerBody, \ + igearset, \ + iscales); \ + } + +#define okapi_makeCreateBaseInt(returnType, allocateExpr, methodName) \ + okapi_makeCreateBaseIntImpl(returnType, allocateExpr, methodName, baseTank, SkidSteerModel); \ + okapi_makeCreateBaseIntImpl(returnType, allocateExpr, methodName, baseXdrive, XDriveModel) + +#define okapi_createAllocExpr ChassisControllerPID out + +#define okapi_createEndExpr \ + out.startThread(); \ + return out + +#define okapi_createPtrAllocExpr auto out = std::make_shared + +#define okapi_createPtrEndExpr \ + out->startThread(); \ + return out + +#define okapi_makeCreateBasePidImpl(returnType, methodName, modelType, fullModelTypeName) \ + static returnType methodName(okapi_##modelType##Params, \ + okapi_baseSensorParams, \ + std::unique_ptr idistanceController, \ + std::unique_ptr iangleController, \ + std::unique_ptr iturnController, \ + okapi_makeCreateEndParams) { \ + okapi_##methodName##AllocExpr( \ + itimeUtil, \ + std::make_shared(okapi_##modelType##Body, \ + okapi_baseSensorBody, \ + toUnderlyingType(igearset.internalGearset)), \ + std::move(idistanceController), \ + std::move(iangleController), \ + std::move(iturnController), \ + igearset, \ + iscales); \ + okapi_##methodName##EndExpr; \ + } + +#define okapi_makeCreateBasePid(returnType, methodName) \ + okapi_makeCreateBasePidImpl(returnType, methodName, baseTank, SkidSteerModel); \ + okapi_makeCreateBasePidImpl(returnType, methodName, baseXdrive, XDriveModel) + +namespace okapi { +class ChassisControllerFactory { + public: + okapi_makeCreateAll(Motor); + okapi_makeCreateAll(MotorGroup); + + okapi_makeCreateBaseInt(ChassisControllerIntegrated, ChassisControllerIntegrated, create); + okapi_makeCreateBaseInt(std::shared_ptr, + std::make_shared, + createPtr); + + okapi_makeCreateBasePid(ChassisControllerPID, create); + okapi_makeCreateBasePid(std::shared_ptr, createPtr); +}; +} // namespace okapi diff --git a/include/okapi/impl/chassis/model/chassisModelFactory.hpp b/include/okapi/impl/chassis/model/chassisModelFactory.hpp new file mode 100644 index 0000000..f7e6461 --- /dev/null +++ b/include/okapi/impl/chassis/model/chassisModelFactory.hpp @@ -0,0 +1,143 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/model/skidSteerModel.hpp" +#include "okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp" +#include "okapi/api/chassis/model/xDriveModel.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include "okapi/impl/device/motor/motorGroup.hpp" +#include "okapi/impl/device/rotarysensor/adiEncoder.hpp" + +namespace okapi { +class ChassisModelFactory { + public: + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +127, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the left and right motors (using the integrated + * encoders). + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + */ + static SkidSteerModel create(Motor ileftSideMotor, + Motor irightSideMotor, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +127, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the left and right motors (using the integrated + * encoders). + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + */ + static SkidSteerModel create(MotorGroup ileftSideMotor, + MotorGroup irightSideMotor, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +127, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the left and right motors (using the integrated + * encoders). + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + */ + static SkidSteerModel create(MotorGroup ileftSideMotor, + MotorGroup irightSideMotor, + ADIEncoder ileftEnc, + ADIEncoder irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for an x drive (wheels at 45 deg from a skid steer drive). When all motors are powered + * +127, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the top left and top right motors (using the + * integrated encoders). + * + * @param itopLeftMotor top left motor + * @param itopRightMotor top right motor + * @param ibottomRightMotor bottom right motor + * @param ibottomLeftMotor bottom left motor + */ + static XDriveModel create(Motor itopLeftMotor, + Motor itopRightMotor, + Motor ibottomRightMotor, + Motor ibottomLeftMotor, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for an x drive (wheels at 45 deg from a skid steer drive). When all motors are powered + * +127, the robot should move forward in a straight line. + * + * This constructor infers the two sensors from the top left and top right motors (using the + * integrated encoders). + * + * @param itopLeftMotor top left motor + * @param itopRightMotor top right motor + * @param ibottomRightMotor bottom right motor + * @param ibottomLeftMotor bottom left motor + */ + static XDriveModel create(Motor itopLeftMotor, + Motor itopRightMotor, + Motor ibottomRightMotor, + Motor ibottomLeftMotor, + ADIEncoder ileftEnc, + ADIEncoder irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +127, the robot should move forward in a straight line. + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + * @param ileftEnc left side encoder + * @param imiddleEnc middle encoder (mounted perpendicular to the left and right side encoders) + * @param irightEnc right side encoder + */ + static ThreeEncoderSkidSteerModel create(Motor ileftSideMotor, + Motor irightSideMotor, + ADIEncoder ileftEnc, + ADIEncoder imiddleEnc, + ADIEncoder irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); + + /** + * Model for a skid steer drive (wheels parallel with robot's direction of motion). When all + * motors are powered +127, the robot should move forward in a straight line. + * + * @param ileftSideMotor left side motor + * @param irightSideMotor right side motor + * @param ileftEnc left side encoder + * @param imiddleEnc middle encoder (mounted perpendicular to the left and right side encoders) + * @param irightEnc right side encoder + */ + static ThreeEncoderSkidSteerModel create(MotorGroup ileftSideMotor, + MotorGroup irightSideMotor, + ADIEncoder ileftEnc, + ADIEncoder imiddleEnc, + ADIEncoder irightEnc, + double imaxVelocity, + double imaxVoltage = 12000); +}; +} // namespace okapi diff --git a/include/okapi/impl/control/async/asyncControllerFactory.hpp b/include/okapi/impl/control/async/asyncControllerFactory.hpp new file mode 100644 index 0000000..6756a37 --- /dev/null +++ b/include/okapi/impl/control/async/asyncControllerFactory.hpp @@ -0,0 +1,260 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/chassis/controller/chassisController.hpp" +#include "okapi/api/control/async/asyncLinearMotionProfileController.hpp" +#include "okapi/api/control/async/asyncMotionProfileController.hpp" +#include "okapi/api/control/async/asyncPosIntegratedController.hpp" +#include "okapi/api/control/async/asyncPosPidController.hpp" +#include "okapi/api/control/async/asyncVelIntegratedController.hpp" +#include "okapi/api/control/async/asyncVelPidController.hpp" +#include "okapi/api/util/mathUtil.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include "okapi/impl/device/motor/motorGroup.hpp" +#include "okapi/impl/device/rotarysensor/adiEncoder.hpp" +#include "okapi/impl/device/rotarysensor/adiGyro.hpp" +#include "okapi/impl/device/rotarysensor/integratedEncoder.hpp" +#include "okapi/impl/device/rotarysensor/potentiometer.hpp" +#include "okapi/impl/util/timeUtilFactory.hpp" + +#define okapi_makePosPID(MotorType) \ + static AsyncPosPIDController posPID(MotorType imotor, \ + double ikP, \ + double ikI, \ + double ikD, \ + double ikBias = 0, \ + std::unique_ptr iderivativeFilter = \ + std::make_unique(), \ + const TimeUtil &itimeUtil = TimeUtilFactory::create()) { \ + return posPID(imotor.getEncoder(), \ + std::make_shared(imotor), \ + ikP, \ + ikI, \ + ikD, \ + ikBias, \ + std::move(iderivativeFilter), \ + itimeUtil); \ + } + +#define okapi_makePosPIDWithSensor(MotorType, SensorType) \ + static AsyncPosPIDController posPID(MotorType imotor, \ + SensorType isensor, \ + double ikP, \ + double ikI, \ + double ikD, \ + double ikBias = 0, \ + std::unique_ptr iderivativeFilter = \ + std::make_unique(), \ + const TimeUtil &itimeUtil = TimeUtilFactory::create()) { \ + return posPID(std::make_shared(isensor), \ + std::make_shared(imotor), \ + ikP, \ + ikI, \ + ikD, \ + ikBias, \ + std::move(iderivativeFilter), \ + itimeUtil); \ + } + +#define okapi_makeVelPID(MotorType) \ + static AsyncVelPIDController velPID(MotorType imotor, \ + double ikP, \ + double ikD, \ + double ikF = 0, \ + double ikSF = 0, \ + double iTPR = imev5TPR, \ + std::unique_ptr iderivativeFilter = \ + std::make_unique(), \ + const TimeUtil &itimeUtil = TimeUtilFactory::create()) { \ + return velPID(imotor.getEncoder(), \ + std::make_shared(imotor), \ + ikP, \ + ikD, \ + ikF, \ + ikSF, \ + iTPR, \ + std::move(iderivativeFilter), \ + itimeUtil); \ + } + +#define okapi_makeVelPIDWithSensor(MotorType, SensorType) \ + static AsyncVelPIDController velPID(MotorType imotor, \ + SensorType ienc, \ + double ikP, \ + double ikD, \ + double ikF = 0, \ + double ikSF = 0, \ + double iTPR = imev5TPR, \ + std::unique_ptr iderivativeFilter = \ + std::make_unique(), \ + const TimeUtil &itimeUtil = TimeUtilFactory::create()) { \ + return velPID(std::make_shared(ienc), \ + std::make_shared(imotor), \ + ikP, \ + ikD, \ + ikF, \ + ikSF, \ + iTPR, \ + std::move(iderivativeFilter), \ + itimeUtil); \ + } + +namespace okapi { +class AsyncControllerFactory { + public: + /** + * A position controller that uses the V5 motor's onboard control. + * + * @param imotor controller input (from the integrated encoder) and output + * @param imaxVelocity the maximum velocity during a profiled movement + */ + static AsyncPosIntegratedController + posIntegrated(Motor imotor, + std::int32_t imaxVelocity = 600, + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A position controller that uses the V5 motor's onboard control. + * + * @param imotor controller input (from the integrated encoder) and output + * @param imaxVelocity the maximum velocity during a profiled movement + */ + static AsyncPosIntegratedController + posIntegrated(MotorGroup imotor, + std::int32_t imaxVelocity = 600, + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A velocity controller that uses the V5 motor's onboard control. + * + * @param imotor controller input (from the integrated encoder) and output + */ + static AsyncVelIntegratedController + velIntegrated(Motor imotor, const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A velocity controller that uses the V5 motor's onboard control. + * + * @param imotor controller input (from the integrated encoder) and output + */ + static AsyncVelIntegratedController + velIntegrated(MotorGroup imotor, const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + okapi_makePosPID(Motor); + okapi_makePosPID(MotorGroup); + okapi_makePosPIDWithSensor(Motor, ADIEncoder); + okapi_makePosPIDWithSensor(Motor, ADIGyro); + okapi_makePosPIDWithSensor(Motor, Potentiometer); + okapi_makePosPIDWithSensor(Motor, IntegratedEncoder); + okapi_makePosPIDWithSensor(MotorGroup, ADIEncoder); + okapi_makePosPIDWithSensor(MotorGroup, ADIGyro); + okapi_makePosPIDWithSensor(MotorGroup, Potentiometer); + okapi_makePosPIDWithSensor(MotorGroup, IntegratedEncoder); + + /** + * A position controller that uses the PID algorithm. + * + * @param iinput controller input + * @param ioutput controller output + * @param ikP proportional gain + * @param ikI integration gain + * @param ikD derivative gain + * @param ikBias output bias (a constant added to the output) + */ + static AsyncPosPIDController + posPID(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + double ikP, + double ikI, + double ikD, + double ikBias = 0, + std::unique_ptr iderivativeFilter = std::make_unique(), + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + okapi_makeVelPID(Motor); + okapi_makeVelPID(MotorGroup); + okapi_makeVelPIDWithSensor(Motor, ADIEncoder); + okapi_makeVelPIDWithSensor(Motor, ADIGyro); + okapi_makeVelPIDWithSensor(Motor, Potentiometer); + okapi_makeVelPIDWithSensor(Motor, IntegratedEncoder); + okapi_makeVelPIDWithSensor(MotorGroup, ADIEncoder); + okapi_makeVelPIDWithSensor(MotorGroup, ADIGyro); + okapi_makeVelPIDWithSensor(MotorGroup, Potentiometer); + okapi_makeVelPIDWithSensor(MotorGroup, IntegratedEncoder); + + /** + * A velocity controller that uses the PD algorithm. + * + * @param iinput controller input + * @param ioutput controller output + * @param ikP proportional gain + * @param ikD derivative gain + * @param ikF feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + */ + static AsyncVelPIDController + velPID(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + double ikP, + double ikD, + double ikF = 0, + double ikSF = 0, + double iTPR = imev5TPR, + std::unique_ptr iderivativeFilter = std::make_unique(), + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A controller which generates and follows 2D motion profiles. + * + * @param imaxVel The maximum possible velocity in m/s. + * @param imaxAccel The maximum possible acceleration in m/s/s. + * @param imaxJerk The maximum possible jerk in m/s/s/s. + * @param ichassis The chassis to control. + */ + static AsyncMotionProfileController + motionProfile(double imaxVel, + double imaxAccel, + double imaxJerk, + const ChassisController &ichassis, + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A controller which generates and follows 2D motion profiles. + * + * @param imaxVel The maximum possible velocity in m/s. + * @param imaxAccel The maximum possible acceleration in m/s/s. + * @param imaxJerk The maximum possible jerk in m/s/s/s. + * @param imodel The chassis model to control. + * @param iwidth The chassis wheelbase width. + */ + static AsyncMotionProfileController + motionProfile(double imaxVel, + double imaxAccel, + double imaxJerk, + const std::shared_ptr &imodel, + const ChassisScales &iscales, + AbstractMotor::GearsetRatioPair ipair, + const TimeUtil &itimeUtil = TimeUtilFactory::create()); + + /** + * A controller which generates and follows 1D motion profiles. + * + * @param imaxVel The maximum possible velocity in m/s. + * @param imaxAccel The maximum possible acceleration in m/s/s. + * @param imaxJerk The maximum possible jerk in m/s/s/s. + * @param ioutput The output to write velocity targets to. + */ + static AsyncLinearMotionProfileController + linearMotionProfile(double imaxVel, + double imaxAccel, + double imaxJerk, + const std::shared_ptr> &ioutput, + const TimeUtil &itimeUtil = TimeUtilFactory::create()); +}; +} // namespace okapi diff --git a/include/okapi/impl/control/iterative/iterativeControllerFactory.hpp b/include/okapi/impl/control/iterative/iterativeControllerFactory.hpp new file mode 100644 index 0000000..a5e29d2 --- /dev/null +++ b/include/okapi/impl/control/iterative/iterativeControllerFactory.hpp @@ -0,0 +1,105 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/iterative/iterativeMotorVelocityController.hpp" +#include "okapi/api/control/iterative/iterativePosPidController.hpp" +#include "okapi/api/control/iterative/iterativeVelPidController.hpp" +#include "okapi/api/util/mathUtil.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include "okapi/impl/device/motor/motorGroup.hpp" + +namespace okapi { +class IterativeControllerFactory { + public: + /** + * Position PID controller. + * + * @param ikP proportional gain + * @param ikI integral gain + * @param ikD derivative gain + * @param ikBias controller bias (constant offset added to the output) + */ + static IterativePosPIDController + posPID(double ikP, + double ikI, + double ikD, + double ikBias = 0, + std::unique_ptr iderivativeFilter = std::make_unique()); + + /** + * Velocity PD controller. + * + * @param ikP proportional gain + * @param ikD derivative gain + * @param ikF feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + */ + static IterativeVelPIDController + velPID(double ikP, + double ikD, + double ikF = 0, + double ikSF = 0, + const VelMathArgs &iparams = VelMathArgs(imev5TPR), + std::unique_ptr iderivativeFilter = std::make_unique()); + + /** + * Velocity PD controller that automatically writes to the motor. + * + * @param imotor output motor + * @param ikP proportional gain + * @param ikD derivative gain + * @param ikF feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + */ + static IterativeMotorVelocityController + motorVelocity(Motor imotor, + double ikP, + double ikD, + double ikF = 0, + double ikSF = 0, + const VelMathArgs &iparams = VelMathArgs(imev5TPR)); + + /** + * Velocity PD controller that automatically writes to the motor. + * + * @param imotor output motor + * @param ikP proportional gain + * @param ikD derivative gain + * @param ikF feed-forward gain + * @param ikSF a feed-forward gain to counteract static friction + */ + static IterativeMotorVelocityController + motorVelocity(MotorGroup imotor, + double ikP, + double ikD, + double ikF = 0, + double ikSF = 0, + const VelMathArgs &iparams = VelMathArgs(imev5TPR)); + + /** + * Velocity PD controller that automatically writes to the motor. + * + * @param imotor output motor + * @param icontroller controller to use + */ + static IterativeMotorVelocityController + motorVelocity(Motor imotor, + std::shared_ptr> icontroller); + + /** + * Velocity PD controller that automatically writes to the motor. + * + * @param imotor output motor + * @param icontroller controller to use + */ + static IterativeMotorVelocityController + motorVelocity(MotorGroup imotor, + std::shared_ptr> icontroller); +}; +} // namespace okapi diff --git a/include/okapi/impl/control/util/controllerRunnerFactory.hpp b/include/okapi/impl/control/util/controllerRunnerFactory.hpp new file mode 100644 index 0000000..8f4b853 --- /dev/null +++ b/include/okapi/impl/control/util/controllerRunnerFactory.hpp @@ -0,0 +1,20 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/util/controllerRunner.hpp" +#include "okapi/impl/util/rate.hpp" + +namespace okapi { +template class ControllerRunnerFactory { + public: + static ControllerRunner create() { + return ControllerRunner(std::make_unique()); + } +}; +} // namespace okapi diff --git a/include/okapi/impl/control/util/pidTunerFactory.hpp b/include/okapi/impl/control/util/pidTunerFactory.hpp new file mode 100644 index 0000000..7330042 --- /dev/null +++ b/include/okapi/impl/control/util/pidTunerFactory.hpp @@ -0,0 +1,48 @@ +/** + * @author Jonathan Bayless, Team BLRS + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/util/pidTuner.hpp" +#include + +namespace okapi { +class PIDTunerFactory { + public: + static PIDTuner create(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + QTime itimeout, + std::int32_t igoal, + double ikPMin, + double ikPMax, + double ikIMin, + double ikIMax, + double ikDMin, + double ikDMax, + std::int32_t inumIterations = 5, + std::int32_t inumParticles = 16, + double ikSettle = 1, + double ikITAE = 2); + + static std::unique_ptr + createPtr(const std::shared_ptr> &iinput, + const std::shared_ptr> &ioutput, + QTime itimeout, + std::int32_t igoal, + double ikPMin, + double ikPMax, + double ikIMin, + double ikIMax, + double ikDMin, + double ikDMax, + std::int32_t inumIterations = 5, + std::int32_t inumParticles = 16, + double ikSettle = 1, + double ikITAE = 2); +}; +} // namespace okapi diff --git a/include/okapi/impl/control/util/settledUtilFactory.hpp b/include/okapi/impl/control/util/settledUtilFactory.hpp new file mode 100644 index 0000000..02b0156 --- /dev/null +++ b/include/okapi/impl/control/util/settledUtilFactory.hpp @@ -0,0 +1,30 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/control/util/settledUtil.hpp" +#include + +namespace okapi { +class SettledUtilFactory { + public: + /** + * A utility class to determine if a control loop has settled based on error. A control loop is + * settled if the error is within atTargetError for atTargetTime. + * + * @param iatTargetError minimum error to be considered settled + * @param iatTargetDerivative minimum error derivative to be considered settled + * @param iatTargetTime minimum time within atTargetError to be considered settled + */ + static SettledUtil + create(double iatTargetError = 50, double iatTargetDerivative = 5, QTime iatTargetTime = 250_ms); + static std::unique_ptr createPtr(double iatTargetError = 50, + double iatTargetDerivative = 5, + QTime iatTargetTime = 250_ms); +}; +} // namespace okapi diff --git a/include/okapi/impl/device/adiUltrasonic.hpp b/include/okapi/impl/device/adiUltrasonic.hpp new file mode 100644 index 0000000..5b3f7c6 --- /dev/null +++ b/include/okapi/impl/device/adiUltrasonic.hpp @@ -0,0 +1,54 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/filter/medianFilter.hpp" +#include + +namespace okapi { +class ADIUltrasonic : public ControllerInput { + public: + /** + * An ultrasonic sensor in the ADI (3-wire) ports. Uses a 5-tap MedianFilter by default. + * + * @param iportTop top port + * @param iportBottom bottom port + */ + ADIUltrasonic(std::uint8_t iportTop, std::uint8_t iportBottom); + + /** + * An ultrasonic sensor in the ADI (3-wire) ports. + * + * @param iportTop top port + * @param iportBottom bottom port + * @param ifilter the filter to use for filtering measurements + */ + ADIUltrasonic(std::uint8_t iportTop, std::uint8_t iportBottom, std::unique_ptr ifilter); + + virtual ~ADIUltrasonic(); + + /** + * Returns the current filtered sensor value. + * + * @return current value + */ + virtual double get(); + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. Calls get(). + */ + virtual double controllerGet() override; + + protected: + pros::ADIUltrasonic ultra; + std::unique_ptr filter; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/button/adiButton.hpp b/include/okapi/impl/device/button/adiButton.hpp new file mode 100644 index 0000000..5a2a32f --- /dev/null +++ b/include/okapi/impl/device/button/adiButton.hpp @@ -0,0 +1,24 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/button/buttonBase.hpp" + +namespace okapi { +class ADIButton : public ButtonBase { + public: + ADIButton(std::uint8_t iport, bool iinverted = false); + + protected: + pros::ADIButton btn; + std::uint8_t port; + + virtual bool currentlyPressed() override; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/button/controllerButton.hpp b/include/okapi/impl/device/button/controllerButton.hpp new file mode 100644 index 0000000..1486e9c --- /dev/null +++ b/include/okapi/impl/device/button/controllerButton.hpp @@ -0,0 +1,27 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/button/buttonBase.hpp" +#include "okapi/impl/device/controllerUtil.hpp" + +namespace okapi { +class ControllerButton : public ButtonBase { + public: + ControllerButton(ControllerDigital ibtn, bool iinverted = false); + + ControllerButton(ControllerId icontroller, ControllerDigital ibtn, bool iinverted = false); + + protected: + pros::Controller controller; + const ControllerDigital btn; + + virtual bool currentlyPressed() override; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/controller.hpp b/include/okapi/impl/device/controller.hpp new file mode 100644 index 0000000..9f5f9da --- /dev/null +++ b/include/okapi/impl/device/controller.hpp @@ -0,0 +1,129 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/impl/device/button/controllerButton.hpp" +#include "okapi/impl/device/controllerUtil.hpp" +#include + +namespace okapi { +class Controller { + public: + Controller(ControllerId iid = ControllerId::master); + + virtual ~Controller(); + + /** + * Returns whether the controller is connected. + * + * @return true if the controller is connected + */ + virtual bool isConnected(); + + /** + * Returns the full connection state of the controller. + * 0 = disconnected + * 1 = tethered + * 2 = VEXnet + * + * @return the connection state of the controller + */ + virtual std::int32_t getConnectionState(); + + /** + * Returns the current analog reading for the channel in the range [-1, 1]. Returns 0 if the + * controller is not connected. + * + * @param ichannel the channel to read + * @return the value of that channel in the range [-1, 1] + */ + virtual float getAnalog(ControllerAnalog ichannel); + + /** + * Returns whether the digital button is currently pressed. Returns false if the controller is + * not connected. + * + * @param ibutton the button to check + * @return true if the button is pressed, false if the controller is not connected + */ + virtual bool getDigital(ControllerDigital ibutton); + + /** + * Returns a ControllerButton for the given button on this controller. + * + * @param ibtn the button + * @return a ControllerButton on this controller + */ + virtual ControllerButton &operator[](ControllerDigital ibtn); + + /** + * Sets text to the controller LCD screen. + * + * @param iline the line number at which the text will be displayed [0-2] + * @param icol the column number at which the text will be displayed [0-14] + * @param itext the string to display + * @return 1 if the operation was successful, PROS_ERR otherwise + */ + virtual std::int32_t setText(std::uint8_t iline, std::uint8_t icol, std::string itext); + + /** + * Clears all of the lines of the controller screen. + * + * @return 1 if the operation was successful, PROS_ERR otherwise + */ + virtual std::int32_t clear(); + + /** + * Clears an individual line of the controller screen. + * + * @param iline the line number to clear + * @return 1 if the operation was successful, PROS_ERR otherwise + */ + virtual std::int32_t clearLine(std::uint8_t iline); + + /** + * Rumble the controller. + * + * Controller rumble activation is currently in beta, so continuous, fast + * updates will not work well. + * + * @param irumblePattern A string consisting of the characters '.', '-', and ' ', where dots are + * short rumbles, dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 + * characters. + * + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t rumble(std::string irumblePattern); + + /** + * Gets the battery capacity of the given controller. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the controller port. + * + * @return the controller's battery capacity + */ + virtual std::int32_t getBatteryCapacity(); + + /** + * Gets the battery level of the given controller. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the controller port. + * + * @return the controller's battery level + */ + virtual std::int32_t getBatteryLevel(); + + protected: + ControllerId m_id; + pros::Controller controller; + static std::array buttonArray; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/controllerUtil.hpp b/include/okapi/impl/device/controllerUtil.hpp new file mode 100644 index 0000000..53ccff1 --- /dev/null +++ b/include/okapi/impl/device/controllerUtil.hpp @@ -0,0 +1,58 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" + +namespace okapi { +/** + * Which controller role this has. + */ +enum class ControllerId { master = 0, partner = 1 }; + +/** + * The analog sticks. + */ +enum class ControllerAnalog { leftX = 0, leftY = 1, rightX = 2, rightY = 3 }; + +/** + * Various buttons. + */ +enum class ControllerDigital { + L1 = 6, + L2 = 7, + R1 = 8, + R2 = 9, + up = 10, + down = 11, + left = 12, + right = 13, + X = 14, + B = 15, + Y = 16, + A = 17 +}; + +class ControllerUtil { + public: + /** + * Maps an `id` to the PROS enum equivalent. + */ + static pros::controller_id_e_t idToProsEnum(ControllerId in); + + /** + * Maps an `analog` to the PROS enum equivalent. + */ + static pros::controller_analog_e_t analogToProsEnum(ControllerAnalog in); + + /** + * Maps a `digital` to the PROS enum equivalent. + */ + static pros::controller_digital_e_t digitalToProsEnum(ControllerDigital in); +}; +} // namespace okapi diff --git a/include/okapi/impl/device/motor/adiMotor.hpp b/include/okapi/impl/device/motor/adiMotor.hpp new file mode 100644 index 0000000..a81e623 --- /dev/null +++ b/include/okapi/impl/device/motor/adiMotor.hpp @@ -0,0 +1,37 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/control/controllerOutput.hpp" + +namespace okapi { +class ADIMotor : public ControllerOutput { + public: + ADIMotor(std::uint8_t iport, bool ireverse = false); + + /** + * Set the voltage to the motor. + * + * @param ivoltage voltage + */ + virtual void moveVoltage(std::int32_t ivoltage) const; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + virtual void controllerSet(double ivalue) override; + + protected: + const pros::ADIMotor motor; + const std::int8_t reversed; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/motor/motor.hpp b/include/okapi/impl/device/motor/motor.hpp new file mode 100644 index 0000000..ea0b295 --- /dev/null +++ b/include/okapi/impl/device/motor/motor.hpp @@ -0,0 +1,556 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/motor/abstractMotor.hpp" + +namespace okapi { +class Motor : public AbstractMotor, public pros::Motor { + public: + /** + * A V5 motor. A negative port number is shorthand for reversing the motor. + * + * @param port the port number + */ + Motor(std::int8_t port); + + explicit Motor(std::uint8_t port, + bool reverse, + AbstractMotor::gearset igearset, + AbstractMotor::encoderUnits encoderUnits = AbstractMotor::encoderUnits::degrees); + + /******************************************************************************/ + /** Motor movement functions **/ + /** **/ + /** These functions allow programmers to make motors move **/ + /******************************************************************************/ + + /** + * Sets the target absolute position for the motor to move to. + * + * This movement is relative to the position of the motor when initialized or + * the position when it was most recently reset with setZeroPosition(). + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The absolute position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveAbsolute(double iposition, std::int32_t ivelocity) override; + + /** + * Sets the relative target position for the motor to move to. + * + * This movement is relative to the current position of the motor. Providing 10.0 as the position + * parameter would result in the motor moving clockwise 10 units, no matter what the current + * position is. + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The relative position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveRelative(double iposition, std::int32_t ivelocity) override; + + /** + * Sets the velocity for the motor. + * + * This velocity corresponds to different actual speeds depending on the gearset + * used for the motor. This results in a range of +-100 for pros::c::red, + * +-200 for green, and +-600 for blue. The velocity + * is held with PID to ensure consistent speed, as opposed to setting the motor's + * voltage. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVelocity(std::int16_t ivelocity) override; + + /** + * Sets the voltage for the motor from -12000 to 12000. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivoltage The new voltage value from -12000 to 12000. + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVoltage(std::int16_t ivoltage) override; + + /** + * Changes the output velocity for a profiled movement (moveAbsolute or moveRelative). This will + * have no effect if the motor is not following a profiled movement. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t modifyProfiledVelocity(std::int32_t ivelocity) override; + + /******************************************************************************/ + /** Motor telemetry functions **/ + /** **/ + /** These functions allow programmers to collect telemetry from motors **/ + /******************************************************************************/ + + /** + * Gets the target position set for the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The target position in its encoder units or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTargetPosition() override; + + /** + * Gets the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's absolute position in its encoder units or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double getPosition() override; + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t tarePosition() override; + + /** + * Gets the velocity commanded to the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The commanded motor velocity from +-100, +-200, or +-600, or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t getTargetVelocity() override; + + /** + * Gets the actual velocity of the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's actual velocity in RPM or PROS_ERR_F if the operation failed, setting + * errno. + */ + virtual double getActualVelocity() override; + + /** + * Gets the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentDraw() override; + + /** + * Gets the direction of movement for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 for moving in the positive direction, -1 for moving in the negative direction, and + * PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getDirection() override; + + /** + * Gets the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's efficiency in percent or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getEfficiency() override; + + /** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the motor's current limit is being exceeded and 0 if the current limit is not + * exceeded, or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverCurrent() override; + + /** + * Checks if the motor's temperature is above its limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the temperature limit is exceeded and 0 if the the temperature is below the limit, + * or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverTemp() override; + + /** + * Checks if the motor is stopped. + * + * Although this function forwards data from the motor, the motor presently does not provide any + * value. This function returns PROS_ERR with errno set to ENOSYS. + * @return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR if the operation + * failed, setting errno + */ + virtual std::int32_t isStopped() override; + + /** + * Checks if the motor is at its zero position. + * + * Although this function forwards data from the motor, the motor presently does not provide any + * value. This function returns PROS_ERR with errno set to ENOSYS. + * + * @return 1 if the motor is at zero absolute position, 0 if the motor has moved from its absolute + * zero, or PROS_ERR if the operation failed, setting errno + */ + virtual std::int32_t getZeroPositionFlag() override; + + /** + * Gets the faults experienced by the motor. Compare this bitfield to the bitmasks in + * pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's faults. 0b00000100 = Current Limit + * Hit + */ + virtual uint32_t getFaults() override; + + /** + * Gets the flags set by the motor's operation. Compare this bitfield to the bitmasks in + * pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's flags. These seem to be unrelated + * to the individual get_specific_flag functions + */ + virtual uint32_t getFlags() override; + + /** + * Gets the raw encoder count of the motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param timestamp A pointer to a time in milliseconds for which the encoder count will be + * returned. If NULL, the timestamp at which the encoder count was read will not be supplied + * + * @return The raw encoder count at the given timestamp or PROS_ERR if the operation failed. + */ + virtual std::int32_t getRawPosition(std::uint32_t *timestamp) override; + + /** + * Gets the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's power draw in Watts or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getPower() override; + + /** + * Gets the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's temperature in degrees Celsius or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTemperature() override; + + /** + * Gets the torque generated by the motor in Newton Metres (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's torque in NM or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getTorque() override; + + /** + * Gets the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's voltage in V or PROS_ERR_F if the operation failed, setting errno. + */ + virtual std::int32_t getVoltage() override; + + /******************************************************************************/ + /** Motor configuration functions **/ + /** **/ + /** These functions allow programmers to configure the behavior of motors **/ + /******************************************************************************/ + + /** + * Sets one of AbstractMotor::brakeMode to the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param imode The new motor brake mode to set for the motor + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setBrakeMode(AbstractMotor::brakeMode imode) override; + + /** + * Gets the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of brakeMode, according to what was set for the motor, or brakeMode::invalid if the + * operation failed, setting errno. + */ + virtual brakeMode getBrakeMode() override; + + /** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new current limit in mA + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setCurrentLimit(std::int32_t ilimit) override; + + /** + * Gets the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current limit in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentLimit() override; + + /** + * Sets one of AbstractMotor::encoderUnits for the motor encoder. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iunits The new motor encoder units + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setEncoderUnits(AbstractMotor::encoderUnits iunits) override; + + /** + * Gets the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of encoderUnits according to what is set for the motor or encoderUnits::invalid if + * the operation failed. + */ + virtual encoderUnits getEncoderUnits() override; + + /** + * Sets one of AbstractMotor::gearset for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param igearset The new motor gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setGearing(AbstractMotor::gearset igearset) override; + + /** + * Gets the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of gearset according to what is set for the motor, or gearset::invalid if the + * operation failed. + */ + virtual gearset getGearing() override; + + /** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ireverse True reverses the motor, false is default + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setReversed(bool ireverse) override; + + /** + * Sets the voltage limit for the motor in Volts. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new voltage limit in Volts + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVoltageLimit(std::int32_t ilimit) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPID(double ikF, double ikP, double ikI, double ikD) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPID(double ikF, double ikP, double ikI, double ikD) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) override; + + /** + * Get the encoder associated with this motor. + * + * @return encoder for this motor + */ + virtual std::shared_ptr getEncoder() override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + virtual void controllerSet(double ivalue) override; + + protected: + AbstractMotor::gearset gearset{AbstractMotor::gearset::green}; +}; + +inline namespace literals { +/** + * Non-reversed motor. + **/ +okapi::Motor operator"" _mtr(unsigned long long iport); + +/** + * Reversed motor. + **/ +okapi::Motor operator"" _rmtr(unsigned long long iport); +} // namespace literals +} // namespace okapi diff --git a/include/okapi/impl/device/motor/motorGroup.hpp b/include/okapi/impl/device/motor/motorGroup.hpp new file mode 100644 index 0000000..72b6959 --- /dev/null +++ b/include/okapi/impl/device/motor/motorGroup.hpp @@ -0,0 +1,548 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/device/motor/abstractMotor.hpp" +#include "okapi/impl/device/motor/motor.hpp" +#include +#include + +namespace okapi { +class MotorGroup : public AbstractMotor { + public: + /** + * A group of V5 motors which act as one motor (i.e. they are mechanically linked). A MotorGroup + * requires at least one motor. If no motors are supplied, a std::invalid_argument exception is + * thrown. + * + * @param imotors the motors in this group + */ + MotorGroup(const std::initializer_list &imotors); + + /******************************************************************************/ + /** Motor movement functions **/ + /** **/ + /** These functions allow programmers to make motors move **/ + /******************************************************************************/ + + /** + * Sets the target absolute position for the motor to move to. + * + * This movement is relative to the position of the motor when initialized or + * the position when it was most recently reset with setZeroPosition(). + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The absolute position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveAbsolute(double iposition, std::int32_t ivelocity) override; + + /** + * Sets the relative target position for the motor to move to. + * + * This movement is relative to the current position of the motor. Providing 10.0 as the position + * parameter would result in the motor moving clockwise 10 units, no matter what the current + * position is. + * + * @note This function simply sets the target for the motor, it does not block program execution + * until the movement finishes. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iposition The relative position to move to in the motor's encoder units + * @param ivelocity The maximum allowable velocity for the movement in RPM + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveRelative(double iposition, std::int32_t ivelocity) override; + + /** + * Sets the velocity for the motor. + * + * This velocity corresponds to different actual speeds depending on the gearset + * used for the motor. This results in a range of +-100 for pros::c::red, + * +-200 for green, and +-600 for blue. The velocity + * is held with PID to ensure consistent speed, as opposed to setting the motor's + * voltage. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVelocity(std::int16_t ivelocity) override; + + /** + * Sets the voltage for the motor from -12000 to 12000. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivoltage The new voltage value from -12000 to 12000. + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t moveVoltage(std::int16_t ivoltage) override; + + /** + * Changes the output velocity for a profiled movement (moveAbsolute or moveRelative). This will + * have no effect if the motor is not following a profiled movement. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ivelocity The new motor velocity from -+-100, +-200, or +-600 depending on the motor's + * gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t modifyProfiledVelocity(std::int32_t ivelocity) override; + + /******************************************************************************/ + /** Motor telemetry functions **/ + /** **/ + /** These functions allow programmers to collect telemetry from motors **/ + /******************************************************************************/ + + /** + * Gets the target position set for the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The target position in its encoder units or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTargetPosition() override; + + /** + * Gets the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's absolute position in its encoder units or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double getPosition() override; + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t tarePosition() override; + + /** + * Gets the velocity commanded to the motor by the user. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The commanded motor velocity from +-100, +-200, or +-600, or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t getTargetVelocity() override; + + /** + * Gets the actual velocity of the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's actual velocity in RPM or PROS_ERR_F if the operation failed, setting + * errno. + */ + virtual double getActualVelocity() override; + + /** + * Gets the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentDraw() override; + + /** + * Gets the direction of movement for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 for moving in the positive direction, -1 for moving in the negative direction, and + * PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getDirection() override; + + /** + * Gets the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's efficiency in percent or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getEfficiency() override; + + /** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the motor's current limit is being exceeded and 0 if the current limit is not + * exceeded, or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverCurrent() override; + + /** + * Checks if the motor's temperature is above its limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return 1 if the temperature limit is exceeded and 0 if the the temperature is below the limit, + * or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t isOverTemp() override; + + /** + * Checks if the motor is stopped. + * + * \note Although this function forwards data from the motor, the motor + * presently + * does not provide any value. This function returns PROS_ERR with errno set to + * ENOSYS. + * + * @return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR if the operation + * failed, setting errno + */ + virtual std::int32_t isStopped() override; + + /** + * Checks if the motor is at its zero position. + * + * Although this function forwards data from the motor, the motor + * presently + * does not provide any value. This function returns PROS_ERR with errno set to + * ENOSYS. + * + * @return 1 if the motor is at zero absolute position, 0 if the motor has moved from its absolute + * zero, or PROS_ERR if the operation failed, setting errno + */ + virtual std::int32_t getZeroPositionFlag() override; + + /** + * Gets the faults experienced by the motor. Compare this bitfield to the bitmasks in + * pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's faults. 0b00000100 = Current Limit + * Hit + */ + virtual uint32_t getFaults() override; + + /** + * Gets the flags set by the motor's operation. Compare this bitfield to the bitmasks in + * pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return A currently unknown bitfield containing the motor's flags. These seem to be unrelated + * to the individual get_specific_flag functions + */ + virtual uint32_t getFlags() override; + + /** + * Gets the raw encoder count of the motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param timestamp A pointer to a time in milliseconds for which the encoder count will be + * returned. If NULL, the timestamp at which the encoder count was read will not be supplied + * + * @return The raw encoder count at the given timestamp or PROS_ERR if the operation failed. + */ + virtual std::int32_t getRawPosition(std::uint32_t *timestamp) override; + + /** + * Gets the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's power draw in Watts or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getPower() override; + + /** + * Gets the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's temperature in degrees Celsius or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double getTemperature() override; + + /** + * Gets the torque generated by the motor in Newton Metres (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's torque in NM or PROS_ERR_F if the operation failed, setting errno. + */ + virtual double getTorque() override; + + /** + * Gets the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's voltage in V or PROS_ERR_F if the operation failed, setting errno. + */ + virtual std::int32_t getVoltage() override; + + /******************************************************************************/ + /** Motor configuration functions **/ + /** **/ + /** These functions allow programmers to configure the behavior of motors **/ + /******************************************************************************/ + + /** + * Sets one of AbstractMotor::brakeMode to the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param imode The new motor brake mode to set for the motor + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setBrakeMode(AbstractMotor::brakeMode imode) override; + + /** + * Gets the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of brakeMode, according to what was set for the motor, or brakeMode::invalid if the + * operation failed, setting errno. + */ + virtual brakeMode getBrakeMode() override; + + /** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new current limit in mA + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setCurrentLimit(std::int32_t ilimit) override; + + /** + * Gets the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return The motor's current limit in mA or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t getCurrentLimit() override; + + /** + * Sets one of AbstractMotor::encoderUnits for the motor encoder. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param iunits The new motor encoder units + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setEncoderUnits(AbstractMotor::encoderUnits iunits) override; + + /** + * Gets the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of encoderUnits according to what is set for the motor or encoderUnits::invalid if + * the operation failed. + */ + virtual encoderUnits getEncoderUnits() override; + + /** + * Sets one of AbstractMotor::gearset for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param igearset The new motor gearset + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setGearing(AbstractMotor::gearset igearset) override; + + /** + * Gets the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @return One of gearset according to what is set for the motor, or gearset::invalid if the + * operation failed. + */ + virtual gearset getGearing() override; + + /** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ireverse True reverses the motor, false is default + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setReversed(bool ireverse) override; + + /** + * Sets the voltage limit for the motor in Volts. + * + * This function uses the following values of errno when an error state is reached: + * EACCES - Another resource is currently trying to access the port. + * + * @param ilimit The new voltage limit in Volts + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVoltageLimit(std::int32_t ilimit) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPID(double ikF, double ikP, double ikI, double ikD) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setPosPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPID(double ikF, double ikP, double ikI, double ikD) override; + + /** + * Sets new PID constants. + * + * @param ikF the feed-forward constant + * @param ikP the proportional constant + * @param ikI the integral constant + * @param ikD the derivative constant + * @param ifilter a constant used for filtering the profile acceleration + * @param ilimit the integral limit + * @param ithreshold the threshold for determining if a position movement has reached its goal + * @param iloopSpeed the rate at which the PID computation is run (in ms) + * @return 1 if the operation was successful or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t setVelPIDFull(double ikF, + double ikP, + double ikI, + double ikD, + double ifilter, + double ilimit, + double ithreshold, + double iloopSpeed) override; + + /** + * Writes the value of the controller output. This method might be automatically called in another + * thread by the controller. The range of input values is expected to be [-1, 1]. + * + * @param ivalue the controller's output in the range [-1, 1] + */ + virtual void controllerSet(double ivalue) override; + + /** + * Get the encoder associated with this motor. + * + * @return encoder for this motor + */ + virtual std::shared_ptr getEncoder() override; + + protected: + std::vector motors; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/rotarysensor/adiEncoder.hpp b/include/okapi/impl/device/rotarysensor/adiEncoder.hpp new file mode 100644 index 0000000..f10f212 --- /dev/null +++ b/include/okapi/impl/device/rotarysensor/adiEncoder.hpp @@ -0,0 +1,43 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" + +namespace okapi { +class ADIEncoder : public ContinuousRotarySensor { + public: + ADIEncoder(std::uint8_t iportTop, std::uint8_t iportBottom, bool ireversed = false); + + /** + * Get the current sensor value. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double get() const override; + + /** + * Reset the sensor to zero. + * + * @return 1 on success, PROS_ERR on fail + */ + virtual std::int32_t reset() override; + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double controllerGet() override; + + protected: + pros::ADIEncoder enc; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/rotarysensor/adiGyro.hpp b/include/okapi/impl/device/rotarysensor/adiGyro.hpp new file mode 100644 index 0000000..4da9527 --- /dev/null +++ b/include/okapi/impl/device/rotarysensor/adiGyro.hpp @@ -0,0 +1,64 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/control/controllerInput.hpp" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" + +namespace okapi { +class ADIGyro : public ContinuousRotarySensor { + public: + /** + * A gyroscope on the given ADI port. If the port has not previously been configured as a gyro, + * then the constructor will block for 1 second for calibration. The gyro measures in tenths of a + * degree, so there are 3600 measurement points per revolution. + * + * @param iport the ADI port number + * @param imultiplier a value multiplied by the gyro heading value + */ + ADIGyro(std::uint8_t iport, double imultiplier = 1); + + virtual ~ADIGyro(); + + /** + * Get the current sensor value. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + double get() const override; + + /** + * Get the current sensor value remapped into the target range ([1800, -1800] by default). + * + * @param iupperBound the upper bound of the range. + * @param ilowerBound the lower bound of the range. + * @return the remapped sensor value. + */ + double getRemapped(double iupperBound = 1800, double ilowerBound = -1800) const + __attribute__((optimize(3))); + + /** + * Reset the sensor to zero. + * + * @return 1 on success, PROS_ERR on fail + */ + std::int32_t reset() override; + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + double controllerGet() override; + + protected: + pros::ADIGyro gyro; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/rotarysensor/integratedEncoder.hpp b/include/okapi/impl/device/rotarysensor/integratedEncoder.hpp new file mode 100644 index 0000000..8defda3 --- /dev/null +++ b/include/okapi/impl/device/rotarysensor/integratedEncoder.hpp @@ -0,0 +1,56 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/rotarysensor/continuousRotarySensor.hpp" +#include "okapi/impl/device/motor/motor.hpp" + +namespace okapi { +class IntegratedEncoder : public ContinuousRotarySensor { + public: + /** + * Integrated motor encoder. Uses the encoder inside the V5 motor. + * + * @param imotor the motor to use the encoder from. + */ + explicit IntegratedEncoder(const pros::Motor &imotor); + + /** + * Integrated motor encoder. Uses the encoder inside the V5 motor. + * + * @param imotor the motor to use the encoder from. + */ + explicit IntegratedEncoder(const okapi::Motor &imotor); + + /** + * Get the current sensor value. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double get() const override; + + /** + * Reset the sensor to zero. + * + * @return 1 on success, PROS_ERR on fail + */ + virtual std::int32_t reset() override; + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double controllerGet() override; + + protected: + pros::Motor motor; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/rotarysensor/potentiometer.hpp b/include/okapi/impl/device/rotarysensor/potentiometer.hpp new file mode 100644 index 0000000..459c9ad --- /dev/null +++ b/include/okapi/impl/device/rotarysensor/potentiometer.hpp @@ -0,0 +1,38 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" +#include "okapi/api/device/rotarysensor/rotarySensor.hpp" + +namespace okapi { +class Potentiometer : public RotarySensor { + public: + Potentiometer(std::uint8_t iport); + + virtual ~Potentiometer(); + + /** + * Get the current sensor value. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double get() const override; + + /** + * Get the sensor value for use in a control loop. This method might be automatically called in + * another thread by the controller. + * + * @return the current sensor value, or ``PROS_ERR`` on a failure. + */ + virtual double controllerGet() override; + + protected: + pros::ADIPotentiometer pot; +}; +} // namespace okapi diff --git a/include/okapi/impl/device/vision.hpp b/include/okapi/impl/device/vision.hpp new file mode 100644 index 0000000..b6fe875 --- /dev/null +++ b/include/okapi/impl/device/vision.hpp @@ -0,0 +1,14 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "api.h" + +namespace okapi { +using pros::Vision; +} // namespace okapi diff --git a/include/okapi/impl/filter/velMathFactory.hpp b/include/okapi/impl/filter/velMathFactory.hpp new file mode 100644 index 0000000..6283c65 --- /dev/null +++ b/include/okapi/impl/filter/velMathFactory.hpp @@ -0,0 +1,41 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/filter/velMath.hpp" +#include + +namespace okapi { +class VelMathFactory { + public: + /** + * Velocity math helper. Calculates filtered velocity. Throws a std::invalid_argument exception + * if iticksPerRev is zero. Averages the last two readings. + * + * @param iticksPerRev number of ticks per revolution (or whatever units you are using) + */ + static VelMath create(double iticksPerRev, QTime isampleTime = 0_ms); + + static std::unique_ptr createPtr(double iticksPerRev, QTime isampleTime = 0_ms); + + /** + * Velocity math helper. Calculates filtered velocity. Throws a std::invalid_argument exception + * if iticksPerRev is zero. + * + * @param iticksPerRev number of ticks per revolution (or whatever units you are using) + * @param ifilter filter used for filtering the calculated velocity + */ + static VelMath + create(double iticksPerRev, std::shared_ptr ifilter, QTime isampleTime = 0_ms); + + static std::unique_ptr + createPtr(double iticksPerRev, std::shared_ptr ifilter, QTime isampleTime = 0_ms); + + static std::unique_ptr createPtr(const VelMathArgs &ivelMathArgs); +}; +} // namespace okapi diff --git a/include/okapi/impl/util/rate.hpp b/include/okapi/impl/util/rate.hpp new file mode 100644 index 0000000..2430abe --- /dev/null +++ b/include/okapi/impl/util/rate.hpp @@ -0,0 +1,52 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/util/abstractRate.hpp" + +namespace okapi { +class Rate : public AbstractRate { + public: + Rate(); + + /** + * Delay the current task such that it runs at the given frequency. The first delay will run for + * 1000/(ihz). Subsequent delays will adjust according to the previous runtime of the task. + * + * @param ihz the frequency + */ + void delay(QFrequency ihz) override; + + /** + * Delay the current task such that it runs every ihz ms. The first delay will run for + * 1000/(ihz). Subsequent delays will adjust according to the previous runtime of the task. + * + * @param ihz the frequency in ms + */ + void delay(int ihz) override; + + /** + * Delay the current task until itime has passed. This method can be used by periodic tasks to + * ensure a consistent execution frequency. + * + * @param itime the time period + */ + void delayUntil(QTime itime) override; + + /** + * Delay the current task until ims milliseconds have passed. This method can be used by + * periodic tasks to ensure a consistent execution frequency. + * + * @param ims the time period + */ + void delayUntil(uint32_t ims) override; + + protected: + std::uint32_t lastTime{0}; +}; +} // namespace okapi diff --git a/include/okapi/impl/util/timeUtilFactory.hpp b/include/okapi/impl/util/timeUtilFactory.hpp new file mode 100644 index 0000000..9d43e3a --- /dev/null +++ b/include/okapi/impl/util/timeUtilFactory.hpp @@ -0,0 +1,27 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/util/timeUtil.hpp" + +namespace okapi { +class TimeUtilFactory { + public: + /** + * Creates a default TimeUtil. + */ + static TimeUtil create(); + + /** + * Creates a TimeUtil with custom SettledUtil params. See SettledUtil docs. + */ + static TimeUtil withSettledUtilParams(double iatTargetError = 50, + double iatTargetDerivative = 5, + QTime iatTargetTime = 250_ms); +}; +} // namespace okapi diff --git a/include/okapi/impl/util/timer.hpp b/include/okapi/impl/util/timer.hpp new file mode 100644 index 0000000..60d3690 --- /dev/null +++ b/include/okapi/impl/util/timer.hpp @@ -0,0 +1,24 @@ +/** + * @author Ryan Benasutti, WPI + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "okapi/api/util/abstractTimer.hpp" + +namespace okapi { +class Timer : public AbstractTimer { + public: + Timer(); + + /** + * Returns the current time in units of QTime. + * + * @return the current time + */ + QTime millis() const override; +}; +} // namespace okapi diff --git a/include/okapi/pathfinder/include/pathfinder.h b/include/okapi/pathfinder/include/pathfinder.h new file mode 100644 index 0000000..8db9223 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder.h @@ -0,0 +1,19 @@ +#ifndef PATHFINDER_H_DEF +#define PATHFINDER_H_DEF + +#include "okapi/pathfinder/include/pathfinder/mathutil.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +#include "okapi/pathfinder/include/pathfinder/fit.h" +#include "okapi/pathfinder/include/pathfinder/spline.h" +#include "okapi/pathfinder/include/pathfinder/trajectory.h" + +#include "okapi/pathfinder/include/pathfinder/modifiers/tank.h" +#include "okapi/pathfinder/include/pathfinder/modifiers/swerve.h" + +#include "okapi/pathfinder/include/pathfinder/followers/encoder.h" +#include "okapi/pathfinder/include/pathfinder/followers/distance.h" + +#include "okapi/pathfinder/include/pathfinder/io.h" + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/fit.h b/include/okapi/pathfinder/include/pathfinder/fit.h new file mode 100644 index 0000000..7d323f9 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/fit.h @@ -0,0 +1,14 @@ +#ifndef PATHFINDER_FIT_H_DEF +#define PATHFINDER_FIT_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +CAPI void pf_fit_hermite_pre(Waypoint a, Waypoint b, Spline *s); +CAPI void pf_fit_hermite_cubic(Waypoint a, Waypoint b, Spline *s); +CAPI void pf_fit_hermite_quintic(Waypoint a, Waypoint b, Spline *s); + +#define FIT_HERMITE_CUBIC &pf_fit_hermite_cubic +#define FIT_HERMITE_QUINTIC &pf_fit_hermite_quintic + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/followers/distance.h b/include/okapi/pathfinder/include/pathfinder/followers/distance.h new file mode 100644 index 0000000..002e81e --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/followers/distance.h @@ -0,0 +1,20 @@ +#ifndef PATHFINDER_FOL_DISTANCE_H_DEF +#define PATHFINDER_FOL_DISTANCE_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +CAPI typedef struct { + double kp, ki, kd, kv, ka; +} FollowerConfig; + +CAPI typedef struct { + double last_error, heading, output; + int segment, finished; +} DistanceFollower; + +CAPI double pathfinder_follow_distance(FollowerConfig c, DistanceFollower *follower, Segment *trajectory, int trajectory_length, double distance); + +CAPI double pathfinder_follow_distance2(FollowerConfig c, DistanceFollower *follower, Segment segment, int trajectory_length, double distance); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/followers/encoder.h b/include/okapi/pathfinder/include/pathfinder/followers/encoder.h new file mode 100644 index 0000000..6d58305 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/followers/encoder.h @@ -0,0 +1,21 @@ +#ifndef PATHFINDER_FOL_ENCODER_H_DEF +#define PATHFINDER_FOL_ENCODER_H_DEF + +#include "okapi/pathfinder/include/pathfinder/structs.h" + +typedef struct { + int initial_position, ticks_per_revolution; + double wheel_circumference; + double kp, ki, kd, kv, ka; +} EncoderConfig; + +typedef struct { + double last_error, heading, output; + int segment, finished; +} EncoderFollower; + +double pathfinder_follow_encoder(EncoderConfig c, EncoderFollower *follower, Segment *trajectory, int trajectory_length, int encoder_tick); + +double pathfinder_follow_encoder2(EncoderConfig c, EncoderFollower *follower, Segment segment, int trajectory_length, int encoder_tick); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/io.h b/include/okapi/pathfinder/include/pathfinder/io.h new file mode 100644 index 0000000..9edcfe5 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/io.h @@ -0,0 +1,27 @@ +#ifndef PATHFINDER_IO_H_DEF +#define PATHFINDER_IO_H_DEF + +#include +#include +#include "okapi/pathfinder/include/pathfinder/structs.h" +#include +#include "okapi/pathfinder/include/pathfinder/lib.h" + +#define CSV_LEADING_STRING "dt,x,y,position,velocity,acceleration,jerk,heading\n" + +CAPI void intToBytes(int n, char *bytes); +CAPI int bytesToInt(char *bytes); +CAPI void longToBytes(unsigned long long n, char *bytes); +CAPI unsigned long long bytesToLong(char *bytes); +CAPI double longToDouble(unsigned long long l); +CAPI unsigned long long doubleToLong(double d); +CAPI void doubleToBytes(double n, char *bytes); +CAPI double bytesToDouble(char *bytes); + +CAPI void pathfinder_serialize(FILE *fp, Segment *trajectory, int trajectory_length); +CAPI int pathfinder_deserialize(FILE *fp, Segment *target); + +CAPI void pathfinder_serialize_csv(FILE *fp, Segment *trajectory, int trajectory_length); +CAPI int pathfinder_deserialize_csv(FILE *fp, Segment *target); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/lib.h b/include/okapi/pathfinder/include/pathfinder/lib.h new file mode 100644 index 0000000..0ba47af --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/lib.h @@ -0,0 +1,10 @@ +#ifndef PATHFINDER_LIB_H_DEF +#define PATHFINDER_LIB_H_DEF + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) + #define CAPI __declspec(dllexport) +#else + #define CAPI +#endif + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/mathutil.h b/include/okapi/pathfinder/include/pathfinder/mathutil.h new file mode 100644 index 0000000..3978044 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/mathutil.h @@ -0,0 +1,20 @@ +#include + +#ifndef PATHFINDER_MATH_UTIL_H_DEF +#define PATHFINDER_MATH_UTIL_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" + +#define PI 3.14159265358979323846 +#define TAU PI*2 + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +CAPI double bound_radians(double angle); + +CAPI double r2d(double angleInRads); + +CAPI double d2r(double angleInDegrees); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/modifiers/swerve.h b/include/okapi/pathfinder/include/pathfinder/modifiers/swerve.h new file mode 100644 index 0000000..bac3740 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/modifiers/swerve.h @@ -0,0 +1,14 @@ +#ifndef PATHFINDER_MOD_SWERVE_H_DEF +#define PATHFINDER_MOD_SWERVE_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +CAPI typedef enum { + SWERVE_DEFAULT +} SWERVE_MODE; + +CAPI void pathfinder_modify_swerve(Segment *original, int length, Segment *front_left, Segment *front_right, + Segment *back_left, Segment *back_right, double wheelbase_width, double wheelbase_depth, SWERVE_MODE mode); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/modifiers/tank.h b/include/okapi/pathfinder/include/pathfinder/modifiers/tank.h new file mode 100644 index 0000000..19b16c8 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/modifiers/tank.h @@ -0,0 +1,9 @@ +#ifndef PATHFINDER_MOD_TANK_H_DEF +#define PATHFINDER_MOD_TANK_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +CAPI void pathfinder_modify_tank(Segment *original, int length, Segment *left, Segment *right, double wheelbase_width); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/spline.h b/include/okapi/pathfinder/include/pathfinder/spline.h new file mode 100644 index 0000000..8c68ae1 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/spline.h @@ -0,0 +1,19 @@ +#ifndef PATHFINDER_SPLINE_H_DEF +#define PATHFINDER_SPLINE_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +#define PATHFINDER_SAMPLES_FAST (int)1000 +#define PATHFINDER_SAMPLES_LOW (int)PATHFINDER_SAMPLES_FAST*10 +#define PATHFINDER_SAMPLES_HIGH (int)PATHFINDER_SAMPLES_LOW*10 + +CAPI Coord pf_spline_coords(Spline s, double percentage); +CAPI double pf_spline_deriv(Spline s, double percentage); +CAPI double pf_spline_deriv_2(double a, double b, double c, double d, double e, double k, double p); +CAPI double pf_spline_angle(Spline s, double percentage); + +CAPI double pf_spline_distance(Spline *s, int sample_count); +CAPI double pf_spline_progress_for_distance(Spline s, double distance, int sample_count); + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/structs.h b/include/okapi/pathfinder/include/pathfinder/structs.h new file mode 100644 index 0000000..5c424d3 --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/structs.h @@ -0,0 +1,43 @@ +#ifndef PATHFINDER_STRUCT_H_DEF +#define PATHFINDER_STRUCT_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" + +CAPI typedef struct { + double x, y, angle; +} Waypoint; + +CAPI typedef struct { + double a, b, c, d, e; + double x_offset, y_offset, angle_offset, knot_distance, arc_length; +} Spline; + +CAPI typedef struct { + double x, y; +} Coord; + +CAPI typedef struct { + double dt, x, y, position, velocity, acceleration, jerk, heading; +} Segment; + +CAPI typedef struct { + double dt, max_v, max_a, max_j, src_v, src_theta, dest_pos, dest_v, dest_theta; + int sample_count; +} TrajectoryConfig; + +CAPI typedef struct { + int filter1, filter2, length; + double dt, u, v, impulse; +} TrajectoryInfo; + +CAPI typedef struct { + Spline *saptr; + double *laptr; + double totalLength; + int length; + int path_length; + TrajectoryInfo info; + TrajectoryConfig config; +} TrajectoryCandidate; + +#endif \ No newline at end of file diff --git a/include/okapi/pathfinder/include/pathfinder/trajectory.h b/include/okapi/pathfinder/include/pathfinder/trajectory.h new file mode 100644 index 0000000..449428e --- /dev/null +++ b/include/okapi/pathfinder/include/pathfinder/trajectory.h @@ -0,0 +1,18 @@ +#ifndef PATHFINDER_TRAJECTORY_H_DEF +#define PATHFINDER_TRAJECTORY_H_DEF + +#include "okapi/pathfinder/include/pathfinder/lib.h" +#include "okapi/pathfinder/include/pathfinder/structs.h" + +CAPI int pathfinder_prepare(Waypoint *path, int path_length, void (*fit)(Waypoint,Waypoint,Spline*), int sample_count, double dt, + double max_velocity, double max_acceleration, double max_jerk, TrajectoryCandidate *cand); +CAPI int pathfinder_generate(TrajectoryCandidate *c, Segment *segments); + +CAPI void pf_trajectory_copy(Segment *src, Segment *dest, int length); + +CAPI TrajectoryInfo pf_trajectory_prepare(TrajectoryConfig c); +CAPI int pf_trajectory_create(TrajectoryInfo info, TrajectoryConfig c, Segment *seg); +CAPI int pf_trajectory_fromSecondOrderFilter(int filter_1_l, int filter_2_l, + double dt, double u, double v, double impulse, int len, Segment *t); + +#endif \ No newline at end of file diff --git a/include/pros/adi.h b/include/pros/adi.h new file mode 100644 index 0000000..b84b574 --- /dev/null +++ b/include/pros/adi.h @@ -0,0 +1,714 @@ +/** + * \file pros/adi.h + * + * Contains prototypes for interfacing with the ADI. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_ADI_H_ +#define _PROS_ADI_H_ + +#include +#ifndef PROS_ERR +#define PROS_ERR (INT32_MAX) +#endif + +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif + +/** + * Represents the port type for an ADI port. + */ +typedef enum adi_port_config_e { + E_ADI_ANALOG_IN = 0, + E_ADI_ANALOG_OUT = 1, + E_ADI_DIGITAL_IN = 2, + E_ADI_DIGITAL_OUT = 3, + +#define _DEPRECATE_DIGITAL_IN __attribute__((deprecated("use E_ADI_DIGITAL_IN instead"))) = E_ADI_DIGITAL_IN +#define _DEPRECATE_ANALOG_IN __attribute__((deprecated("use E_ADI_ANALOG_IN instead"))) = E_ADI_ANALOG_IN + + E_ADI_SMART_BUTTON _DEPRECATE_DIGITAL_IN, + E_ADI_SMART_POT _DEPRECATE_ANALOG_IN, + + E_ADI_LEGACY_BUTTON _DEPRECATE_DIGITAL_IN, + E_ADI_LEGACY_POT _DEPRECATE_ANALOG_IN, + E_ADI_LEGACY_LINE_SENSOR _DEPRECATE_ANALOG_IN, + E_ADI_LEGACY_LIGHT_SENSOR _DEPRECATE_ANALOG_IN, + E_ADI_LEGACY_GYRO = 10, + E_ADI_LEGACY_ACCELEROMETER _DEPRECATE_ANALOG_IN, + +#undef _DEPRECATE_DIGITAL_IN +#undef _DEPRECATE_ANALOG_IN + + E_ADI_LEGACY_SERVO = 12, + E_ADI_LEGACY_PWM = 13, + + E_ADI_LEGACY_ENCODER = 14, + E_ADI_LEGACY_ULTRASONIC = 15, + + E_ADI_TYPE_UNDEFINED = 255, + E_ADI_ERR = PROS_ERR +} adi_port_config_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define ADI_ANALOG_IN pros::E_ADI_ANALOG_IN +#define ADI_ANALOG_OUT pros::E_ADI_ANALOG_OUT +#define ADI_DIGITAL_IN pros::E_ADI_DIGITAL_IN +#define ADI_DIGITAL_OUT pros::E_ADI_DIGITAL_OUT +#define ADI_SMART_BUTTON pros::E_ADI_SMART_BUTTON +#define ADI_SMART_POT pros::E_ADI_SMART_POT +#define ADI_LEGACY_BUTTON pros::E_ADI_LEGACY_BUTTON +#define ADI_LEGACY_POT pros::E_ADI_LEGACY_POT +#define ADI_LEGACY_LINE_SENSOR pros::E_ADI_LEGACY_LINE_SENSOR +#define ADI_LEGACY_LIGHT_SENSOR pros::E_ADI_LEGACY_LIGHT_SENSOR +#define ADI_LEGACY_GYRO pros::E_ADI_LEGACY_GYRO +#define ADI_LEGACY_ACCELEROMETER pros::E_ADI_LEGACY_ACCELEROMETER +#define ADI_LEGACY_SERVO pros::E_ADI_LEGACY_SERVO +#define ADI_LEGACY_PWM pros::E_ADI_LEGACY_PWM +#define ADI_LEGACY_ENCODER pros::E_ADI_LEGACY_ENCODER +#define ADI_LEGACY_ULTRASONIC pros::E_ADI_LEGACY_ULTRASONIC +#define ADI_TYPE_UNDEFINED pros::E_ADI_TYPE_UNDEFINED +#define ADI_ERR pros::E_ADI_ERR +#else +#define ADI_ANALOG_IN E_ADI_ANALOG_IN +#define ADI_ANALOG_OUT E_ADI_ANALOG_OUT +#define ADI_DIGITAL_IN E_ADI_DIGITAL_IN +#define ADI_DIGITAL_OUT E_ADI_DIGITAL_OUT +#define ADI_SMART_BUTTON E_ADI_SMART_BUTTON +#define ADI_SMART_POT E_ADI_SMART_POT +#define ADI_LEGACY_BUTTON E_ADI_LEGACY_BUTTON +#define ADI_LEGACY_POT E_ADI_LEGACY_POT +#define ADI_LEGACY_LINE_SENSOR E_ADI_LEGACY_LINE_SENSOR +#define ADI_LEGACY_LIGHT_SENSOR E_ADI_LEGACY_LIGHT_SENSOR +#define ADI_LEGACY_GYRO E_ADI_LEGACY_GYRO +#define ADI_LEGACY_ACCELEROMETER E_ADI_LEGACY_ACCELEROMETER +#define ADI_LEGACY_SERVO E_ADI_LEGACY_SERVO +#define ADI_LEGACY_PWM E_ADI_LEGACY_PWM +#define ADI_LEGACY_ENCODER E_ADI_LEGACY_ENCODER +#define ADI_LEGACY_ULTRASONIC E_ADI_LEGACY_ULTRASONIC +#define ADI_TYPE_UNDEFINED E_ADI_TYPE_UNDEFINED +#define ADI_ERR E_ADI_ERR +#endif +#endif + +#define NUM_ADI_PORTS 8 + +#ifdef __cplusplus +namespace c { +#endif + +/******************************************************************************/ +/** General ADI Use Functions **/ +/** **/ +/** These functions allow for interaction with any ADI port type **/ +/******************************************************************************/ + +/** + * Gets the configuration for the given ADI port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') for which to return + * the configuration + * + * \return The ADI configuration for the given port + */ +adi_port_config_e_t adi_port_get_config(uint8_t port); + +/** + * Gets the value for the given ADI port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') for which the value + * will be returned + * + * \return The value stored for the given port + */ +int32_t adi_port_get_value(uint8_t port); + +/** + * Configures an ADI port to act as a given sensor type. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_port_set_config(uint8_t port, adi_port_config_e_t type); + +/** + * Sets the value for the given ADI port. + * + * This only works on ports configured as outputs, and the behavior will change + * depending on the configuration of the port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') for which the value + * will be set + * \param value + * The value to set the ADI port to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_port_set_value(uint8_t port, int32_t value); + +/******************************************************************************/ +/** PROS 2 Compatibility Functions **/ +/** **/ +/** These functions provide similar functionality to the PROS 2 API **/ +/******************************************************************************/ + +/** + * Used for adi_digital_write() to specify a logic HIGH state to output. + * + * In reality, using any non-zero expression or "true" will work to set a pin to + * HIGH. + */ +#define HIGH 1 +/** + * Used for adi_digital_write() to specify a logic LOW state to output. + * + * In reality, using a zero expression or "false" will work to set a pin to LOW. + */ +#define LOW 0 + +/** + * adi_pin_mode() state for a digital input. + */ +#define INPUT 0x00 +/** + * adi_pin_mode() state for a digital output. + */ +#define OUTPUT 0x01 +/** + * adi_pin_mode() state for an analog input. + */ +#define INPUT_ANALOG 0x02 + +/** + * adi_pin_mode() state for an analog output. + */ +#define OUTPUT_ANALOG 0x03 + +/** + * Calibrates the analog sensor on the specified port and returns the new + * calibration value. + * + * This method assumes that the true sensor value is not actively changing at + * this time and computes an average from approximately 500 samples, 1 ms apart, + * for a 0.5 s period of calibration. The average value thus calculated is + * returned and stored for later calls to the adi_analog_read_calibrated() and + * adi_analog_read_calibrated_HR() functions. These functions will return + * the difference between this value and the current sensor value when called. + * + * Do not use this function when the sensor value might be unstable + * (gyro rotation, accelerometer movement). + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an analog input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to calibrate (from 1-8, 'a'-'h', 'A'-'H') + * + * \return The average sensor value computed by this function + */ +int32_t adi_analog_calibrate(uint8_t port); + +/** + * Gets the 12-bit value of the specified port. + * + * The value returned is undefined if the analog pin has been switched to a + * different mode. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an analog input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port (from 1-8, 'a'-'h', 'A'-'H') for which the value will be + * returned + * + * \return The analog sensor value, where a value of 0 reflects an input voltage + * of nearly 0 V and a value of 4095 reflects an input voltage of nearly 5 V + */ +int32_t adi_analog_read(uint8_t port); + +/** + * Gets the 12 bit calibrated value of an analog input port. + * + * The adi_analog_calibrate() function must be run first. This function is + * inappropriate for sensor values intended for integration, as round-off error + * can accumulate causing drift over time. Use adi_analog_read_calibrated_HR() + * instead. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an analog input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port (from 1-8, 'a'-'h', 'A'-'H') for which the value will be + * returned + * + * \return The difference of the sensor value from its calibrated default from + * -4095 to 4095 + */ +int32_t adi_analog_read_calibrated(uint8_t port); + +/** + * Gets the 16 bit calibrated value of an analog input port. + * + * The adi_analog_calibrate() function must be run first. This is intended for + * integrated sensor values such as gyros and accelerometers to reduce drift due + * to round-off, and should not be used on a sensor such as a line tracker + * or potentiometer. + * + * The value returned actually has 16 bits of "precision", even though the ADC + * only reads 12 bits, so that error induced by the average value being between + * two values when integrated over time is trivial. Think of the value as the + * true value times 16. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an analog input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port (from 1-8, 'a'-'h', 'A'-'H') for which the value will be + * returned + * + * \return The difference of the sensor value from its calibrated default from + * -16384 to 16384 + */ +int32_t adi_analog_read_calibrated_HR(uint8_t port); + +/** + * Gets the digital value (1 or 0) of a port configured as a digital input. + * + * If the port is configured as some other mode, the digital value which + * reflects the current state of the poprt is returned, which may or may not + * differ from the currently set value. The return value is undefined for ports + * configured as any mode other than a Digital Input. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as a digital input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to read (from 1-8, 'a'-'h', 'A'-'H') + * + * \return True if the pin is HIGH, or false if it is LOW + */ +int32_t adi_digital_read(uint8_t port); + +/** + * Gets a rising-edge case for a digital button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under the + * same circumstances, so only one task should call this function for any given + * button. E.g., Task A calls this function for buttons 1 and 2. Task B may call + * this function for button 3, but should not for buttons 1 or 2. A typical + * use-case for this function is to call inside opcontrol to detect new button + * presses, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as a digital input. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to read (from 1-8, 'a'-'h', 'A'-'H') + * + * \return 1 if the button is pressed and had not been pressed + * the last time this function was called, 0 otherwise. + */ +int32_t adi_digital_get_new_press(uint8_t port); + +/** + * Sets the digital value (1 or 0) of a port configured as a digital output. + * + * If the port is configured as some other mode, behavior is undefined. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as a digital output. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to read (from 1-8, 'a'-'h', 'A'-'H') + * \param value + * An expression evaluating to "true" or "false" to set the output to + * HIGH or LOW respectively, or the constants HIGH or LOW themselves + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_digital_write(uint8_t port, const bool value); + +/** + * Configures the port as an input or output with a variety of settings. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to read (from 1-8, 'a'-'h', 'A'-'H') + * \param mode + * One of INPUT, INPUT_ANALOG, INPUT_FLOATING, OUTPUT, or OUTPUT_OD + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_pin_mode(uint8_t port, uint8_t mode); + +/** + * Sets the speed of the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Motor. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to set (from 1-8, 'a'-'h', 'A'-'H') + * \param speed + * The new signed speed; -127 is full reverse and 127 is full forward, + * with 0 being off + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_motor_set(uint8_t port, int8_t speed); + +/** + * Gets the last set speed of the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Motor. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to get (from 1-8, 'a'-'h', 'A'-'H') + * + * \return The last set speed of the motor on the given port + */ +int32_t adi_motor_get(uint8_t port); + +/** + * Stops the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Motor. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to set (from 1-8, 'a'-'h', 'A'-'H') + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_motor_stop(uint8_t port); + +/** + * Reference type for an initialized encoder. + * + * This merely contains the port number for the encoder, unlike its use as an + * object to store encoder data in PROS 2. + */ +typedef int32_t adi_encoder_t; + +/** + * Gets the number of ticks recorded by the encoder. + * + * There are 360 ticks in one revolution. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Encoder. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param enc + * The adi_encoder_t object from adi_encoder_init() to read + * + * \return The signed and cumulative number of counts since the last start or + * reset + */ +int32_t adi_encoder_get(adi_encoder_t enc); + +/** + * Creates an encoder object and configures the specified ports accordingly. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Encoder. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port_top + * The "top" wire from the encoder sensor with the removable cover side + * UP + * \param port_bottom + * The "bottom" wire from the encoder sensor + * \param reverse + * If "true", the sensor will count in the opposite direction + * + * \return An adi_encoder_t object to be stored and used for later calls to + * encoder functions + */ +adi_encoder_t adi_encoder_init(uint8_t port_top, uint8_t port_bottom, const bool reverse); + +/** + * Sets the encoder value to zero. + * + * It is safe to use this method while an encoder is enabled. It is not + * necessary to call this method before stopping or starting an encoder. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Encoder. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param enc + * The adi_encoder_t object from adi_encoder_init() to reset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_encoder_reset(adi_encoder_t enc); + +/** + * Disables the encoder and voids the configuration on its ports. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Encoder. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param enc + * The adi_encoder_t object from adi_encoder_init() to stop + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_encoder_shutdown(adi_encoder_t enc); + +/** + * Reference type for an initialized ultrasonic. + * + * This merely contains the port number for the ultrasonic, unlike its use as an + * object to store ultrasonic data in PROS 2. + */ +typedef int32_t adi_ultrasonic_t; + +/** + * Gets the current ultrasonic sensor value in centimeters. + * + * If no object was found, zero is returned. If the ultrasonic sensor was never + * started, the return value is undefined. Round and fluffy objects can cause + * inaccurate values to be returned. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Ultrasonic. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param ult + * The adi_ultrasonic_t object from adi_ultrasonic_init() to read + * + * \return The distance to the nearest object in m^-4 (10000 indicates 1 meter), + * measured from the sensor's mounting points. + */ +int32_t adi_ultrasonic_get(adi_ultrasonic_t ult); + +/** + * Creates an ultrasonic object and configures the specified ports accordingly. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Ultrasonic. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port_ping + * The port connected to the orange OUTPUT cable. This should be in the + * next highest port following port_echo. + * \param port_echo + * The port connected to the yellow INPUT cable. This should be in port + * 1, 3, 5, or 7 ('A', 'C', 'E', 'G'). + * + * \return An adi_ultrasonic_t object to be stored and used for later calls to + * ultrasonic functions + */ +adi_ultrasonic_t adi_ultrasonic_init(uint8_t port_ping, uint8_t port_echo); + +/** + * Disables the ultrasonic sensor and voids the configuration on its ports. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Ultrasonic. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param ult + * The adi_ultrasonic_t object from adi_ultrasonic_init() to stop + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_ultrasonic_shutdown(adi_ultrasonic_t ult); + +/** + * Reference type for an initialized gyroscope. + * + * This merely contains the port number for the gyroscope, unlike its use as an + * object to store gyro data in PROS 2. + */ +typedef int32_t adi_gyro_t; + +/** + * Gets the current gyro angle in tenths of a degree. Unless a multiplier is + * applied to the gyro, the return value will be a whole number representing + * the number of degrees of rotation times 10. + * + * There are 360 degrees in a circle, thus the gyro will return 3600 for one + * whole rotation. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Gyro. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param gyro + * The adi_gyro_t object for which the angle will be returned + * + * \return The gyro angle in degrees. + */ +double adi_gyro_get(adi_gyro_t gyro); + +/** + * Initializes a gyroscope on the given port. If the given port has not + * previously been configured as a gyro, then this function starts a 1300 ms + * calibration period. + * + * It is highly recommended that this function be called from initialize() when + * the robot is stationary to ensure proper calibration. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to initialize as a gyro (from 1-8, 'a'-'h', 'A'-'H') + * \param multiplier + * A scalar value that will be multiplied by the gyro heading value + * supplied by the ADI + * + * \return An adi_gyro_t object containing the given port, or PROS_ERR if the + * initialization failed. + */ +adi_gyro_t adi_gyro_init(uint8_t port, double multiplier); + +/** + * Resets the gyroscope value to zero. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Gyro. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param gyro + * The adi_gyro_t object for which the angle will be returned + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_gyro_reset(adi_gyro_t gyro); + +/** + * Disables the gyro and voids the configuration on its port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports, or the given + * port is not configured as an ADI Gyro. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param gyro + * The adi_gyro_t object to be shut down + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t adi_gyro_shutdown(adi_gyro_t gyro); + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif + +#endif // _PROS_ADI_H_ diff --git a/include/pros/adi.hpp b/include/pros/adi.hpp new file mode 100644 index 0000000..a2d420e --- /dev/null +++ b/include/pros/adi.hpp @@ -0,0 +1,534 @@ +/** + * \file pros/adi.hpp + * + * Contains prototypes for interfacing with the ADI. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_ADI_HPP_ +#define _PROS_ADI_HPP_ + +#include "pros/adi.h" + +#include + +namespace pros { +class ADIPort { + public: + /** + * Configures an ADI port to act as a given sensor type. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + */ + ADIPort(std::uint8_t port, adi_port_config_e_t type = E_ADI_TYPE_UNDEFINED); + + virtual ~ADIPort(void); + + /** + * Gets the configuration for the given ADI port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The ADI configuration for the given port + */ + std::int32_t get_config(void) const; + + /** + * Gets the value for the given ADI port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The value stored for the given port + */ + std::int32_t get_value(void) const; + + /** + * Configures an ADI port to act as a given sensor type. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \param type + * The configuration type for the port + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_config(adi_port_config_e_t type) const; + + /** + * Sets the value for the given ADI port. + * + * This only works on ports configured as outputs, and the behavior will + * change depending on the configuration of the port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \param value + * The value to set the ADI port to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_value(std::int32_t value) const; + + protected: + ADIPort(void); + std::uint8_t _port; +}; + +class ADIAnalogIn : private ADIPort { + public: + /** + * Configures an ADI port to act as an Analog Input. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + ADIAnalogIn(std::uint8_t port); + + /** + * Calibrates the analog sensor on the specified port and returns the new + * calibration value. + * + * This method assumes that the true sensor value is not actively changing at + * this time and computes an average from approximately 500 samples, 1 ms + * apart, for a 0.5 s period of calibration. The average value thus calculated + * is returned and stored for later calls to the + * pros::ADIAnalogIn::get_value_calibrated() and + * pros::ADIAnalogIn::get_value_calibrated_HR() functions. These functions + * will return the difference between this value and the current sensor value + * when called. + * + * Do not use this function when the sensor value might be unstable (gyro + * rotation, accelerometer movement). + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The average sensor value computed by this function + */ + std::int32_t calibrate(void) const; + + /** + * Gets the 12 bit calibrated value of an analog input port. + * + * The pros::ADIAnalogIn::calibrate() function must be run first. This + * function is inappropriate for sensor values intended for integration, as + * round-off error can accumulate causing drift over time. Use + * pros::ADIAnalogIn::get_value_calibrated_HR() instead. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The difference of the sensor value from its calibrated default from + * -4095 to 4095 + */ + std::int32_t get_value_calibrated(void) const; + + /** + * Gets the 16 bit calibrated value of an analog input port. + * + * The pros::ADIAnalogIn::calibrate() function must be run first. This is + * intended for integrated sensor values such as gyros and accelerometers to + * reduce drift due to round-off, and should not be used on a sensor such as a + * line tracker or potentiometer. + * + * The value returned actually has 16 bits of "precision", even though the ADC + * only reads 12 bits, so that error induced by the average value being + * between two values when integrated over time is trivial. Think of the value + * as the true value times 16. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The difference of the sensor value from its calibrated default from + * -16384 to 16384 + */ + std::int32_t get_value_calibrated_HR(void) const; + + /** + * Gets the 12-bit value of the specified port. + * + * The value returned is undefined if the analog pin has been switched to a + * different mode. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The analog sensor value, where a value of 0 reflects an input + * voltage of nearly 0 V and a value of 4095 reflects an input voltage of + * nearly 5 V + */ + using ADIPort::get_value; +}; + +using ADIPotentiometer = ADIAnalogIn; +using ADILineSensor = ADIAnalogIn; +using ADILightSensor = ADIAnalogIn; +using ADIAccelerometer = ADIAnalogIn; + +class ADIAnalogOut : private ADIPort { + public: + /** + * Configures an ADI port to act as an Analog Output. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + */ + ADIAnalogOut(std::uint8_t port); + + /** + * Sets the value for the given ADI port. + * + * This only works on ports configured as outputs, and the behavior will + * change depending on the configuration of the port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \param value + * The value to set the ADI port to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + using ADIPort::set_value; +}; + +class ADIDigitalOut : private ADIPort { + public: + /** + * Configures an ADI port to act as a Digital Output. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + */ + ADIDigitalOut(std::uint8_t port, bool init_state = LOW); + + /** + * Sets the value for the given ADI port. + * + * This only works on ports configured as outputs, and the behavior will + * change depending on the configuration of the port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \param value + * The value to set the ADI port to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + using ADIPort::set_value; +}; + +class ADIDigitalIn : private ADIPort { + public: + /** + * Configures an ADI port to act as a Digital Input. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + */ + ADIDigitalIn(std::uint8_t port); + + /** + * Gets a rising-edge case for a digital button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. Task B + * may call this function for button 3, but should not for buttons 1 or 2. A + * typical use-case for this function is to call inside opcontrol to detect + * new button presses, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return 1 if the button is pressed and had not been pressed the last time + * this function was called, 0 otherwise. + */ + std::int32_t get_new_press(void) const; + + /** + * Gets the value for the given ADI port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The value stored for the given port + */ + using ADIPort::get_value; +}; + +using ADIButton = ADIDigitalIn; + +class ADIMotor : private ADIPort { + public: + /** + * Configures an ADI port to act as a Motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure + * \param type + * The configuration type for the port + */ + ADIMotor(std::uint8_t port); + + /** + * Stops the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t stop(void) const; + + /** + * Sets the speed of the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \param value + * The new signed speed; -127 is full reverse and 127 is full forward, + * with 0 being off + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + using ADIPort::set_value; + + /** + * Gets the last set speed of the motor on the given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The last set speed of the motor on the given port + */ + using ADIPort::get_value; +}; + +class ADIEncoder : private ADIPort { + public: + /** + * Configures a set of ADI ports to act as an Encoder. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port_top + * The "top" wire from the encoder sensor with the removable cover side + * UP + * \param port_bottom + * The "bottom" wire from the encoder sensor + * \param reverse + * If "true", the sensor will count in the opposite direction + */ + ADIEncoder(std::uint8_t port_top, std::uint8_t port_bottom, bool reversed = false); + + /** + * Sets the encoder value to zero. + * + * It is safe to use this method while an encoder is enabled. It is not + * necessary to call this method before stopping or starting an encoder. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t reset(void) const; + + /** + * Gets the number of ticks recorded by the encoder. + * + * There are 360 ticks in one revolution. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The signed and cumulative number of counts since the last start or + * reset + */ + std::int32_t get_value(void) const; +}; + +class ADIUltrasonic : private ADIPort { + public: + /** + * Configures a set of ADI ports to act as an Ultrasonic. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports. + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port_ping + * The port connected to the orange OUTPUT cable. This should be in the + * next highest port following port_echo. + * \param port_echo + * The port connected to the yellow INPUT cable. This should be in port + * 1, 3, 5, or 7 ('A', 'C', 'E', 'G'). + */ + ADIUltrasonic(std::uint8_t port_ping, std::uint8_t port_echo); + + /** + * Gets the current ultrasonic sensor value in centimeters. + * + * If no object was found, zero is returned. If the ultrasonic sensor was + * never started, the return value is undefined. Round and fluffy objects can + * cause inaccurate values to be returned. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The distance to the nearest object in m^-4 (10000 indicates 1 + * meter), measured from the sensor's mounting points. + */ + using ADIPort::get_value; +}; + +class ADIGyro : private ADIPort { + public: + /** + * Initializes a gyroscope on the given port. If the given port has not + * previously been configured as a gyro, then this function starts a 1300ms + * calibration period. + * + * It is highly recommended that an ADIGyro object be created in initialize() + * when the robot is stationary to ensure proper calibration. If an ADIGyro + * object is declared at the global scope, a hardcoded 1300ms delay at the + * beginning of initialize will be necessary to ensure that the gyro's + * returned values are correct at the beginning of autonomous/opcontrol. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of ADI Ports + * EACCES - Another resource is currently trying to access the ADI. + * + * \param port + * The ADI port to initialize as a gyro (from 1-8, 'a'-'h', 'A'-'H') + * \param multiplier + * A scalar value that will be multiplied by the gyro heading value + * supplied by the ADI + */ + ADIGyro(std::uint8_t port, double multiplier = 1); + + ~ADIGyro(void) override; + + /** + * Gets the current gyro angle in tenths of a degree. Unless a multiplier is + * applied to the gyro, the return value will be a whole number representing + * the number of degrees of rotation times 10. + * + * There are 360 degrees in a circle, thus the gyro will return 3600 for one + * whole rotation. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return The gyro angle in degrees. + */ + double get_value(void) const; + + /** + * Resets the gyroscope value to zero. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the ADI. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t reset(void) const; +}; +} // namespace pros + +#endif // _PROS_ADI_HPP_ diff --git a/include/pros/api_legacy.h b/include/pros/api_legacy.h new file mode 100644 index 0000000..a193b2e --- /dev/null +++ b/include/pros/api_legacy.h @@ -0,0 +1,108 @@ +/** + * \file pros/api_legacy.h + * + * PROS 2 Legacy API header + * + * Contains declarations for functions that are name-compatible with the PROS 2 + * API. Some functions from the PROS 2 API are not useful or cannot be + * implemented in PROS 3, but most common functions are available. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_API_LEGACY_H_ +#define _PROS_API_LEGACY_H_ + +#include "api.h" + +#ifdef __cplusplus +#define _NAMESPACE pros:: +#define _CNAMESPACE pros::c:: +#else +#define _NAMESPACE +#define _CNAMESPACE +#endif + +/** + * From adi.h + */ +#define analogCalibrate(port) adi_analog_calibrate(port) +#define analogRead(port) adi_analog_read(port) +#define analogReadCalibrated(port) adi_analog_read_calibrated(port) +#define analogReadCalibratedHR(port) adi_analog_read_calibrated_HR(port) +#define digitalRead(port) adi_digital_read(port) +#define digitalWrite(port, value) adi_digital_write(port, value) +#define pinMode(port, mode) adi_pin_mode(port, mode) +#define adiMotorSet(port, speed) adi_motor_set(port, speed) +#define adiMotorGet(port) adi_motor_get(port) +#define adiMotorStop(port) adi_motor_stop(port) +#define encoderGet(enc) adi_encoder_get(enc) +#define encoderInit(portTop, portBottom, reverse) adi_encoder_init(portTop, portBottom, reverse) +#define encoderShutdown(enc) adi_encoder_shutdown(enc) +#define ultrasonicGet(ult) adi_ultrasonic_get(ult) +#define ultrasonicInit(portEcho, portPing) adi_ultrasonic_init(portEcho, portPing) +#define ultrasonicShutdown(ult) adi_ultrasonic_shutdown(ult) + +typedef _CNAMESPACE adi_encoder_t Encoder; +typedef _CNAMESPACE adi_ultrasonic_t Ultrasonic; + +/** + * From llemu.h + */ +#define lcdInit lcd_initialize +#define lcdReadButtons lcd_read_buttons +#define lcdClear lcd_clear +#define lcdClearLine lcd_clear_line +#define lcdShutdown lcd_shutdown +#define lcdPrint(line, fmt, ...) lcd_print(line, fmt, __VA_ARGS__) +#define lcdSetText(line, text) lcd_set_text(line, text) + +/** + * From misc.h + */ +#define isEnabled() (!competition_is_disabled()) +#define isAutonomous competition_is_autonomous +#define isOnline competition_is_connected +#define isJoystickConnected(id) controller_is_connected(id) +#define joystickGetAnalog(id, channel) controller_get_analog(id, channel) + +/** + * From rtos.h + */ +#define taskCreate(taskCode, stackDepth, parameters, priority) \ + task_create(taskCode, parameters, priority, stackDepth, "") +#define taskDelete(task) task_delete(task) +#define taskDelay task_delay +#define taskDelayUntil(previousWakeTime, cycleTime) task_delay_until(previousWakeTime, cycleTime) +#define taskPriorityGet(task) task_get_priority(task) +#define taskPrioritySet(task, newPriority) task_priority_set(task, newPriority) +#define taskGetState(task) task_get_state(task) +#define taskSuspend(task) task_suspend(task) +#define taskResume(task) task_resume(task) +#define taskGetCount task_get_count +#define mutexCreate mutex_create +#define mutexTake(mutex, blockTime) mutex_take(mutex, blockTime) +#define mutexGive(mutex) mutex_give(mutex) + +typedef _NAMESPACE task_t TaskHandle; +typedef _NAMESPACE mutex_t Mutex; + +/** + * From motors.h + */ +#define motorSet(port, speed) motor_move(port, speed) +#define motorGet(port) motor_get_voltage(port) +#define motorStop(port) motor_move(port, 0) + +#undef _NAMESPACE +#undef _CNAMESPACE + +#endif // _PROS_API_LEGACY_H_ diff --git a/include/pros/apix.h b/include/pros/apix.h new file mode 100644 index 0000000..ec2712e --- /dev/null +++ b/include/pros/apix.h @@ -0,0 +1,546 @@ +/** + * \file pros/apix.h + * + * PROS Extended API header + * + * Contains additional declarations for use by advaned users of PROS. These + * functions do not typically have as much error handling or require deeper + * knowledge of real time operating systems. + * + * Visit https://pros.cs.purdue.edu/v5/extended/api.html to learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_API_EXTENDED_H_ +#define _PROS_API_EXTENDED_H_ + +#include "api.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wall" +#include "display/lvgl.h" +#pragma GCC diagnostic pop + +#ifdef __cplusplus +namespace pros::c { +extern "C" { +#endif + +/******************************************************************************/ +/** RTOS FACILITIES **/ +/** **/ +/** **/ +/**See https://pros.cs.purdue.edu/v5/extended/multitasking.html to learn more**/ +/******************************************************************************/ + +typedef void* queue_t; +typedef void* sem_t; + +/** + * Unblocks a task in the Blocked state (e.g. waiting for a delay, on a + * semaphore, etc.). + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#abort_delay for + * details. + */ +bool task_abort_delay(task_t task); + +/** + * Notify a task when a target task is being deleted. + * + * This function will configure the PROS kernel to call + * task_notify_ext(task_to_notify, value, action, NULL) when target_task is + * deleted. + * + * + * \param target_task + * The task being watched for deletion + * \param task_to_notify + * The task to notify when target_task is deleted + * \param value + * The value to supply to task_notify_ext + * \param notify_action + * The action to supply to task_notify_ext + */ +void task_notify_when_deleting(task_t target_task, task_t task_to_notify, uint32_t value, + notify_action_e_t notify_action); + +/** + * Creates a recursive mutex which can be locked recursively by the owner. + * + * See + * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes + * for details. + * + * \return A newly created recursive mutex. + */ +mutex_t mutex_recursive_create(void); + +/** + * Takes a recursive mutex. + * + * See + * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes + * for details. + * + * \param mutex + * A mutex handle created by mutex_recursive_create + * \param wait_time + * Amount of time to wait before timing out + * + * \return 1 if the mutex was obtained, 0 otherwise + */ +bool mutex_recursive_take(mutex_t mutex, uint32_t timeout); + +/** + * Gives a recursive mutex. + * + * See + * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes + * for details. + * + * \param mutex + * A mutex handle created by mutex_recursive_create + * + * \return 1 if the mutex was obtained, 0 otherwise + */ +bool mutex_recursive_give(mutex_t mutex); + +/** + * Returns a handle to the current owner of a mutex. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#extra for + * details. + * + * \param mutex + * A mutex handle + * + * \return A handle to the current task that owns the mutex, or NULL if the + * mutex isn't owned. + */ +task_t mutex_get_owner(mutex_t mutex); + +/** + * Creates a counting sempahore. + * + * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for + *details. + * + * \param max_count + * The maximum count value that can be reached. + * \param init_count + * The initial count value assigned to the new semaphore. + * + * \return A newly created semaphore. If an error occurred, NULL will be + * returned and errno can be checked for hints as to why sem_create failed. + */ +sem_t sem_create(uint32_t max_count, uint32_t init_count); + +/** + * Deletes a semaphore (or binary semaphore) + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#semaphores for + * details. + * + * \param sem + * Semaphore to delete + */ +void sem_delete(sem_t sem); + +/** + * Creates a binary semaphore. + * + * See + * https://pros.cs.purdue.edu/v5/extended/multitasking#.htmlbinary_semaphores + * for details. + * + * \return A newly created semaphore. + */ +sem_t sem_binary_create(void); + +/** + * Waits for the semaphore's value to be greater than 0. If the value is already + * greater than 0, this function immediately returns. + * + * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for + * details. + * + * \param sem + * Semaphore to wait on + * \param timeout + * Time to wait before the semaphore's becomes available. A timeout of 0 + * can be used to poll the sempahore. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the semaphore was successfully take, false otherwise. If + * false is returned, then errno is set with a hint about why the sempahore + * couldn't be taken. + */ +bool sem_wait(sem_t sem, uint32_t timeout); + +/** + * Increments a semaphore's value. + * + * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for + * details. + * + * \param sem + * Semaphore to post + * + * \return True if the value was incremented, false otherwise. If false is + * returned, then errno is set with a hint about why the semaphore couldn't be + * taken. + */ +bool sem_post(sem_t sem); + +/** + * Returns the current value of the semaphore. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#extra for + * details. + * + * \param sem + * A semaphore handle + * + * \return The current value of the semaphore (e.g. the number of resources + * available) + */ +uint32_t sem_get_count(sem_t sem); + +/** + * Creates a queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param length + * The maximum number of items that the queue can contain. + * \param item_size + * The number of bytes each item in the queue will require. + * + * \return A handle to a newly created queue, or NULL if the queue cannot be + * created. + */ +queue_t queue_create(uint32_t length, uint32_t item_size); + +/** + * Posts an item to the front of a queue. The item is queued by copy, not by + * reference. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle + * \param item + * A pointer to the item that will be placed on the queue. + * \param timeout + * Time to wait for space to become available. A timeout of 0 can be used + * to attempt to post without blocking. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the item was preprended, false otherwise. + */ +bool queue_prepend(queue_t queue, const void* item, uint32_t timeout); + +/** + * Posts an item to the end of a queue. The item is queued by copy, not by + * reference. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle + * \param item + * A pointer to the item that will be placed on the queue. + * \param timeout + * Time to wait for space to become available. A timeout of 0 can be used + * to attempt to post without blocking. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the item was preprended, false otherwise. + */ +bool queue_append(queue_t queue, const void* item, uint32_t timeout); + +/** + * Receive an item from a queue without removing the item from the queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle + * \param buffer + * Pointer to a buffer to which the received item will be copied + * \param timeout + * Time to wait for space to become available. A timeout of 0 can be used + * to attempt to post without blocking. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if an item was copied into the buffer, false otherwise. + */ +bool queue_peek(queue_t queue, void* const buffer, uint32_t timeout); + +/** + * Receive an item from the queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle + * \param buffer + * Pointer to a buffer to which the received item will be copied + * \param timeout + * Time to wait for space to become available. A timeout of 0 can be used + * to attempt to post without blocking. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if an item was copied into the buffer, false otherwise. + */ +bool queue_recv(queue_t queue, void* const buffer, uint32_t timeout); + +/** + * Return the number of messages stored in a queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle. + * + * \return The number of messages available in the queue. + */ +uint32_t queue_get_waiting(const queue_t queue); + +/** + * Return the number of spaces left in a queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * The queue handle. + * + * \return The number of spaces available in the queue. + */ +uint32_t queue_get_available(const queue_t queue); + +/** + * Delete a queue. + * + * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for + * details. + * + * \param queue + * Queue handle to delete + */ +void queue_delete(queue_t queue); + +/** + * Resets a queue to an empty state + * + * \param queue + * Queue handle to reset + */ +void queue_reset(queue_t queue); + +/******************************************************************************/ +/** Device Registration **/ +/******************************************************************************/ + +/* + * List of possible v5 devices + * + * This list contains all current V5 Devices, and mirrors V5_DeviceType from the + * api. + */ +typedef enum v5_device_e { + E_DEVICE_NONE = 0, + E_DEVICE_MOTOR = 2, + E_DEVICE_RADIO = 8, + E_DEVICE_VISION = 11, + E_DEVICE_ADI = 12, + E_DEVICE_GENERIC = 129, + E_DEVICE_UNDEFINED = 255 +} v5_device_e_t; + +/* + * Registers a device in the given port + * + * Registers a device of the given type in the given port into the registry, if + * that type of device is detected to be plugged in to that port. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21), or a + * a different device than specified is plugged in. + * EADDRINUSE - The port is already registered to another device. + * + * \param port + * The port number to register the device + * \param device + * The type of device to register + * + * \return 1 upon success, PROS_ERR upon failure + */ +int registry_bind_port(uint8_t port, v5_device_e_t device_type); + +/* + * Deregisters a devices from the given port + * + * Removes the device registed in the given port, if there is one. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * + * \param port + * The port number to deregister + * + * \return 1 upon success, PROS_ERR upon failure + */ +int registry_unbind_port(uint8_t port); + +/******************************************************************************/ +/** Filesystem **/ +/******************************************************************************/ +/** + * Control settings of the serial driver. + * + * \param action + * An action to perform on the serial driver. See the SERCTL_* macros for + * details on the different actions. + * \param extra_arg + * An argument to pass in based on the action + */ +int32_t serctl(const uint32_t action, void* const extra_arg); + +/** + * Control settings of the microSD card driver. + * + * \param action + * An action to perform on the microSD card driver. See the USDCTL_* macros + * for details on the different actions. + * \param extra_arg + * An argument to pass in based on the action + */ +// Not yet implemented +// int32_t usdctl(const uint32_t action, void* const extra_arg); + +/** + * Control settings of the way the file's driver treats the file + * + * \param file + * A valid file descriptor number + * \param action + * An action to perform on the file's driver. See the *CTL_* macros for + * details on the different actions. Note that the action passed in must + * match the correct driver (e.g. don't perform a SERCTL_* action on a + * microSD card file) + * \param extra_arg + * An argument to pass in based on the action + */ +int32_t fdctl(int file, const uint32_t action, void* const extra_arg); + +/** + * Action macro to pass into serctl or fdctl that activates the stream + * identifier. + * + * When used with serctl, the extra argument must be the little endian + * representation of the stream identifier (e.g. "sout" -> 0x74756f73) + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_ACTIVATE 10 + +/** + * Action macro to pass into serctl or fdctl that deactivates the stream + * identifier. + * + * When used with serctl, the extra argument must be the little endian + * representation of the stream identifier (e.g. "sout" -> 0x74756f73) + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_DEACTIVATE 11 + +/** + * Action macro to pass into fdctl that enables blocking writes for the file + * + * The extra argument is not used with this action, provide any value (e.g. + * NULL) instead + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_BLKWRITE 12 + +/** + * Action macro to pass into fdctl that makes writes non-blocking for the file + * + * The extra argument is not used with this action, provide any value (e.g. + * NULL) instead + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_NOBLKWRITE 13 + +/** + * Action macro to pass into serctl that enables advanced stream multiplexing + * capabilities + * + * The extra argument is not used with this action, provide any value (e.g. + * NULL) instead + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_ENABLE_COBS 14 + +/** + * Action macro to pass into serctl that disables advanced stream multiplexing + * capabilities + * + * The extra argument is not used with this action, provide any value (e.g. + * NULL) instead + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial + * to learn more. + */ +#define SERCTL_DISABLE_COBS 15 + +/** + * Action macro to check if there is data available from the Generic Serial + * Device + * + * The extra argument is not used with this action, provide any value (e.g. + * NULL) instead + */ +#define DEVCTL_FIONREAD 16 + +/** + * Action macro to set the Generic Serial Device's baudrate. + * + * The extra argument is the baudrate. + */ +#define DEVCTL_SET_BAUDRATE 17 + +#ifdef __cplusplus +} +} +#endif + +#endif // _PROS_API_EXTENDED_H_ diff --git a/include/pros/colors.h b/include/pros/colors.h new file mode 100644 index 0000000..5a7ad90 --- /dev/null +++ b/include/pros/colors.h @@ -0,0 +1,171 @@ +/* + * \file pros/colors.h + * + * Contains macro definitions of colors (as `uint32_t`) + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018 Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License v. 2.0. If a copy of the MPL was not distributed with this + * file You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_COLORS_H_ +#define _PROS_COLORS_H_ + +#define RGB2COLOR(R, G, B) ((R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff)) +#define COLOR2R(COLOR) ((COLOR >> 16) & 0xff) +#define COLOR2G(COLOR) ((COLOR >> 8) && 0xff) +#define COLOR2B(COLOR) (COLOR & 0xff) + +#define COLOR_ALICE_BLUE 0x00F0F8FF +#define COLOR_ANTIQUE_WHITE 0x00FAEBD7 +#define COLOR_AQUA 0x0000FFFF +#define COLOR_AQUAMARINE 0x007FFFD4 +#define COLOR_AZURE 0x00F0FFFF +#define COLOR_BEIGE 0x00F5F5DC +#define COLOR_BISQUE 0x00FFE4C4 +#define COLOR_BLACK 0x00000000 +#define COLOR_BLANCHED_ALMOND 0x00FFEBCD +#define COLOR_BLUE 0x000000FF +#define COLOR_BLUE_VIOLET 0x008A2BE2 +#define COLOR_BROWN 0x00A52A2A +#define COLOR_BURLY_WOOD 0x00DEB887 +#define COLOR_CADET_BLUE 0x005F9EA0 +#define COLOR_CHARTREUSE 0x007FFF00 +#define COLOR_CHOCOLATE 0x00D2691E +#define COLOR_CORAL 0x00FF7F50 +#define COLOR_CORNFLOWER_BLUE 0x006495ED +#define COLOR_CORNSILK 0x00FFF8DC +#define COLOR_CRIMSON 0x00DC143C +#define COLOR_CYAN 0x0000FFFF +#define COLOR_DARK_BLUE 0x0000008B +#define COLOR_DARK_CYAN 0x00008B8B +#define COLOR_DARK_GOLDENROD 0x00B8860B +#define COLOR_DARK_GRAY 0x00A9A9A9 +#define COLOR_DARK_GREEN 0x00006400 +#define COLOR_DARK_KHAKI 0x00BDB76B +#define COLOR_DARK_MAGENTA 0x008B008B +#define COLOR_DARK_OLIVE_GREEN 0x00556B2F +#define COLOR_DARK_ORANGE 0x00FF8C00 +#define COLOR_DARK_ORCHID 0x009932CC +#define COLOR_DARK_RED 0x008B0000 +#define COLOR_DARK_SALMON 0x00E9967A +#define COLOR_DARK_SEA_GREEN 0x008FBC8F +#define COLOR_DARK_SLATE_GRAY 0x002F4F4F +#define COLOR_DARK_TURQUOISE 0x0000CED1 +#define COLOR_DARK_VIOLET 0x009400D3 +#define COLOR_DEEP_PINK 0x00FF1493 +#define COLOR_DEEP_SKY_BLUE 0x0000BFFF +#define COLOR_DIM_GRAY 0x00696969 +#define COLOR_DODGER_BLUE 0x001E90FF +#define COLOR_FIRE_BRICK 0x00B22222 +#define COLOR_FLORAL_WHITE 0x00FFFAF0 +#define COLOR_FOREST_GREEN 0x00228B22 +#define COLOR_FUCHSIA 0x00FF00FF +#define COLOR_GAINSBORO 0x00DCDCDC +#define COLOR_GHOST_WHITE 0x00F8F8FF +#define COLOR_GOLD 0x00FFD700 +#define COLOR_GOLDENROD 0x00DAA520 +#define COLOR_GRAY 0x00808080 +#define COLOR_GREEN 0x00008000 +#define COLOR_GREEN_YELLOW 0x00ADFF2F +#define COLOR_HONEYDEW 0x00F0FFF0 +#define COLOR_HOT_PINK 0x00FF69B4 +#define COLOR_INDIAN_RED 0x00CD5C5C +#define COLOR_INDIGO 0x004B0082 +#define COLOR_IVORY 0x00FFFFF0 +#define COLOR_KHAKI 0x00F0E68C +#define COLOR_LAVENDER 0x00E6E6FA +#define COLOR_LAVENDER_BLUSH 0x00FFF0F5 +#define COLOR_LAWN_GREEN 0x007CFC00 +#define COLOR_LEMON_CHIFFON 0x00FFFACD +#define COLOR_LIGHT_BLUE 0x00ADD8E6 +#define COLOR_LIGHT_CORAL 0x00F08080 +#define COLOR_LIGHT_CYAN 0x00E0FFFF +#define COLOR_LIGHT_GOLDENROD_YELLOW 0x00FAFAD2 +#define COLOR_LIGHT_GREEN 0x0090EE90 +#define COLOR_LIGHT_GRAY 0x00D3D3D3 +#define COLOR_LIGHT_PINK 0x00FFB6C1 +#define COLOR_LIGHT_SALMON 0x00FFA07A +#define COLOR_LIGHT_SEA_GREEN 0x0020B2AA +#define COLOR_LIGHT_SKY_BLUE 0x0087CEFA +#define COLOR_LIGHT_SLATE_GRAY 0x00778899 +#define COLOR_LIGHT_STEEL_BLUE 0x00B0C4DE +#define COLOR_LIGHT_YELLOW 0x00FFFFE0 +#define COLOR_LIME 0x0000FF00 +#define COLOR_LIME_GREEN 0x0032CD32 +#define COLOR_LINEN 0x00FAF0E6 +#define COLOR_MAGENTA 0x00FF00FF +#define COLOR_MAROON 0x00800000 +#define COLOR_MEDIUM_AQUAMARINE 0x0066CDAA +#define COLOR_MEDIUM_BLUE 0x000000CD +#define COLOR_MEDIUM_ORCHID 0x00BA55D3 +#define COLOR_MEDIUM_PURPLE 0x009370DB +#define COLOR_MEDIUM_SEA_GREEN 0x003CB371 +#define COLOR_MEDIUM_SLATE_BLUE 0x007B68EE +#define COLOR_MEDIUM_SPRING_GREEN 0x0000FA9A +#define COLOR_MEDIUM_TURQUOISE 0x0048D1CC +#define COLOR_MEDIUM_VIOLET_RED 0x00C71585 +#define COLOR_MIDNIGHT_BLUE 0x00191970 +#define COLOR_MINT_CREAM 0x00F5FFFA +#define COLOR_MISTY_ROSE 0x00FFE4E1 +#define COLOR_MOCCASIN 0x00FFE4B5 +#define COLOR_NAVAJO_WHITE 0x00FFDEAD +#define COLOR_NAVY 0x00000080 +#define COLOR_OLD_LACE 0x00FDF5E6 +#define COLOR_OLIVE 0x00808000 +#define COLOR_OLIVE_DRAB 0x006B8E23 +#define COLOR_ORANGE 0x00FFA500 +#define COLOR_ORANGE_RED 0x00FF4500 +#define COLOR_ORCHID 0x00DA70D6 +#define COLOR_PALE_GOLDENROD 0x00EEE8AA +#define COLOR_PALE_GREEN 0x0098FB98 +#define COLOR_PALE_TURQUOISE 0x00AFEEEE +#define COLOR_PALE_VIOLET_RED 0x00DB7093 +#define COLOR_PAPAY_WHIP 0x00FFEFD5 +#define COLOR_PEACH_PUFF 0x00FFDAB9 +#define COLOR_PERU 0x00CD853F +#define COLOR_PINK 0x00FFC0CB +#define COLOR_PLUM 0x00DDA0DD +#define COLOR_POWDER_BLUE 0x00B0E0E6 +#define COLOR_PURPLE 0x00800080 +#define COLOR_RED 0x00FF0000 +#define COLOR_ROSY_BROWN 0x00BC8F8F +#define COLOR_ROYAL_BLUE 0x004169E1 +#define COLOR_SADDLE_BROWN 0x008B4513 +#define COLOR_SALMON 0x00FA8072 +#define COLOR_SANDY_BROWN 0x00F4A460 +#define COLOR_SEA_GREEN 0x002E8B57 +#define COLOR_SEASHELL 0x00FFF5EE +#define COLOR_SIENNA 0x00A0522D +#define COLOR_SILVER 0x00C0C0C0 +#define COLOR_SKY_BLUE 0x0087CEEB +#define COLOR_SLATE_BLUE 0x006A5ACD +#define COLOR_SLATE_GRAY 0x00708090 +#define COLOR_SNOW 0x00FFFAFA +#define COLOR_SPRING_GREEN 0x0000FF7F +#define COLOR_STEEL_BLUE 0x004682B4 +#define COLOR_TAN 0x00D2B48C +#define COLOR_TEAL 0x00008080 +#define COLOR_THISTLE 0x00D8BFD8 +#define COLOR_TOMATO 0x00FF6347 +#define COLOR_TURQUOISE 0x0040E0D0 +#define COLOR_VIOLET 0x00EE82EE +#define COLOR_WHEAT 0x00F5DEB3 +#define COLOR_WHITE 0x00FFFFFF +#define COLOR_WHITE_SMOKE 0x00F5F5F5 +#define COLOR_YELLOW 0x00FFFF00 +#define COLOR_YELLOW_GREEN 0x009ACD32 +#define COLOR_DARK_GREY COLOR_DARK_GRAY +#define COLOR_DARK_SLATE_GREY COLOR_DARK_SLATE_GRAY +#define COLOR_DIM_GREY COLOR_DIM_GRAY +#define COLOR_GREY COLOR_GRAY +#define COLOR_LIGHT_GREY COLOR_LIGHT_GRAY +#define COLOR_LIGHT_SLATE_GREY COLOR_LIGHT_SLATE_GRAY +#define COLOR_SLATE_GREY COLOR_SLATE_GRAY + +#endif // _PROS_COLORS_H_ diff --git a/include/pros/llemu.h b/include/pros/llemu.h new file mode 100644 index 0000000..20f90d8 --- /dev/null +++ b/include/pros/llemu.h @@ -0,0 +1,231 @@ +/* + * \file pros/llemu.h + * + * Legacy LCD Emulator + * + * This file defines a high-level API for emulating the three-button, UART-based + * VEX LCD, containing a set of functions that facilitate the use of a software- + * emulated version of the classic VEX LCD module. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/llemu.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_LLEMU_H_ +#define _PROS_LLEMU_H_ + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#include "display/lvgl.h" +#pragma GCC diagnostic pop + +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif + +typedef void (*lcd_btn_cb_fn_t)(void); + +#define LCD_BTN_LEFT 4 +#define LCD_BTN_CENTER 2 +#define LCD_BTN_RIGHT 1 + +typedef struct lcd_s { + lv_obj_t* frame; + lv_obj_t* screen; + lv_obj_t* lcd_text[8]; + lv_obj_t* btn_container; + lv_obj_t* btns[3]; // < 0 => left; 1 => center; 2 => right + lcd_btn_cb_fn_t callbacks[3]; // < 0 => left; 1 => center; 2 => right + volatile uint8_t touch_bits; // < 4 => left; 2 => center; 1 => right (no + // multitouch support) +} lcd_s_t; + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Checks whether the emulated three-button LCD has already been initialized. + * + * \return True if the LCD has been initialized or false if not. + */ +bool lcd_is_initialized(void); + +/** + * Creates an emulation of the three-button, UART-based VEX LCD on the display. + * + * \return True if the LCD was successfully initialized, or false if it has + * already been initialized. + */ +bool lcd_initialize(void); + +/** + * Turns off the Legacy LCD Emulator. + * + * Calling this function will clear the entire display, and you will not be able + * to call any further LLEMU functions until another call to lcd_initialize. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_shutdown(void); + +/** + * Displays a formatted string on the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line on which to display the text [0-7] + * \param fmt + * Format string + * \param ... + * Optional list of arguments for the format string + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_print(int16_t line, const char* fmt, ...); + +/** + * Displays a string on the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line on which to display the text [0-7] + * \param text + * The text to display + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_set_text(int16_t line, const char* text); + +/** + * Clears the contents of the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_clear(void); + +/** + * Clears the contents of a line of the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line to clear + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_clear_line(int16_t line); + +/** + * Registers a callback function for the leftmost button. + * + * When the leftmost button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t (void (*cb)(void)) + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_register_btn0_cb(lcd_btn_cb_fn_t cb); + +/** + * Registers a callback function for the center button. + * + * When the center button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t (void (*cb)(void)) + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_register_btn1_cb(lcd_btn_cb_fn_t cb); + +/** + * Registers a callback function for the rightmost button. + * + * When the rightmost button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t (void (*cb)(void)) + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool lcd_register_btn2_cb(lcd_btn_cb_fn_t cb); + +/** + * Gets the button status from the emulated three-button LCD. + * + * The value returned is a 3-bit integer where 1 0 0 indicates the left button + * is pressed, 0 1 0 indicates the center button is pressed, and 0 0 1 + * indicates the right button is pressed. 0 is returned if no buttons are + * currently being pressed. + * + * Note that this function is provided for legacy API compatibility purposes, + * with the caveat that the V5 touch screen does not actually support pressing + * multiple points on the screen at the same time. + * + * \return The buttons pressed as a bit mask + */ +uint8_t lcd_read_buttons(void); + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif +#endif // _PROS_LLEMU_H_ diff --git a/include/pros/llemu.hpp b/include/pros/llemu.hpp new file mode 100644 index 0000000..2b0890e --- /dev/null +++ b/include/pros/llemu.hpp @@ -0,0 +1,199 @@ +/* + * \file pros/llemu.hpp + * + * Legacy LCD Emulator + * + * This file defines a high-level API for emulating the three-button, UART-based + * VEX LCD, containing a set of functions that facilitate the use of a software- + * emulated version of the classic VEX LCD module. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/llemu.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_LLEMU_HPP_ +#define _PROS_LLEMU_HPP_ + +#include +#include + +#include "pros/llemu.h" + +namespace pros { +namespace lcd { +/** + * Checks whether the emulated three-button LCD has already been initialized. + * + * \return True if the LCD has been initialized or false if not. + */ +bool is_initialized(void); + +/** + * Creates an emulation of the three-button, UART-based VEX LCD on the display. + * + * \return True if the LCD was successfully initialized, or false if it has + * already been initialized. + */ +bool initialize(void); + +/** + * Turns off the Legacy LCD Emulator. + * + * Calling this function will clear the entire display, and you will not be able + * to call any further LLEMU functions until another call to lcd_initialize. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool shutdown(void); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +namespace { +template +T convert_args(T arg) { + return arg; +} +const char* convert_args(const std::string& arg) { + return arg.c_str(); +} +} // namespace +#pragma GCC diagnostic pop + +/** + * Displays a formatted string on the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line on which to display the text [0-7] + * \param fmt + * Format string + * \param ... + * Optional list of arguments for the format string + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +template +bool print(std::int16_t line, const char* fmt, Params... args) { + return pros::c::lcd_print(line, fmt, convert_args(args)...); +} + +/** + * Displays a string on the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line on which to display the text [0-7] + * \param text + * The text to display + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool set_text(std::int16_t line, std::string text); + +/** + * Clears the contents of the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool clear(void); + +/** + * Clears the contents of a line of the emulated three-button LCD screen. + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The LCD has not been initialized. Call lcd_initialize() first. + * EINVAL - The line number specified is not in the range [0-7] + * + * \param line + * The line to clear + * + * \return True if the operation was successful, or false otherwise, setting + * errno values as specified above. + */ +bool clear_line(std::int16_t line); + +using lcd_btn_cb_fn_t = void (*)(void); + +/** + * Registers a callback function for the leftmost button. + * + * When the leftmost button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t(void (*cb)(void)) + */ +void register_btn0_cb(lcd_btn_cb_fn_t cb); + +/** + * Registers a callback function for the center button. + * + * When the center button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t(void (*cb)(void)) + */ +void register_btn1_cb(lcd_btn_cb_fn_t cb); + +/** + * Registers a callback function for the rightmost button. + * + * When the rightmost button on the emulated three-button LCD is pressed, the + * user-provided callback function will be invoked. + * + * \param cb + * A callback function of type lcd_btn_cb_fn_t(void (*cb)(void)) + */ +void register_btn2_cb(lcd_btn_cb_fn_t cb); + +/** + * Gets the button status from the emulated three-button LCD. + * + * The value returned is a 3-bit integer where 1 0 0 indicates the left button + * is pressed, 0 1 0 indicates the center button is pressed, and 0 0 1 + * indicates the right button is pressed. 0 is returned if no buttons are + * currently being pressed. + * + * Note that this function is provided for legacy API compatibility purposes, + * with the caveat that the V5 touch screen does not actually support pressing + * multiple points on the screen at the same time. + * + * \return The buttons pressed as a bit mask + */ +std::uint8_t read_buttons(void); +} // namespace lcd +} // namespace pros + +#endif // _PROS_LLEMU_HPP_ diff --git a/include/pros/misc.h b/include/pros/misc.h new file mode 100644 index 0000000..18bf25b --- /dev/null +++ b/include/pros/misc.h @@ -0,0 +1,432 @@ +/** + * \file pros/misc.h + * + * Contains prototypes for miscellaneous functions pertaining to the controller, + * battery, and competition control. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/controller.html to + * learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reservered. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_MISC_H_ +#define _PROS_MISC_H_ + +#include + +#define NUM_V5_PORTS (22) + +/******************************************************************************/ +/** V5 Competition **/ +/******************************************************************************/ +#define COMPETITION_DISABLED (1 << 0) +#define COMPETITION_AUTONOMOUS (1 << 1) +#define COMPETITION_CONNECTED (1 << 2) + +/** + * Get the current status of the competition control. + * + * \return The competition control status as a mask of bits with + * COMPETITION_{ENABLED,AUTONOMOUS,CONNECTED}. + */ +#ifdef __cplusplus +extern "C" { +namespace pros { +namespace c { +#endif +uint8_t competition_get_status(void); +#ifdef __cplusplus +} +} +} +#endif +#define competition_is_disabled() ((competition_get_status() & COMPETITION_DISABLED) != 0) +#define competition_is_connected() ((competition_get_status() & COMPETITION_CONNECTED) != 0) +#define competition_is_autonomous() ((competition_get_status() & COMPETITION_AUTONOMOUS) != 0) + +/******************************************************************************/ +/** V5 Controller **/ +/******************************************************************************/ +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif + +typedef enum { E_CONTROLLER_MASTER = 0, E_CONTROLLER_PARTNER } controller_id_e_t; + +typedef enum { + E_CONTROLLER_ANALOG_LEFT_X = 0, + E_CONTROLLER_ANALOG_LEFT_Y, + E_CONTROLLER_ANALOG_RIGHT_X, + E_CONTROLLER_ANALOG_RIGHT_Y +} controller_analog_e_t; + +typedef enum { + E_CONTROLLER_DIGITAL_L1 = 6, + E_CONTROLLER_DIGITAL_L2, + E_CONTROLLER_DIGITAL_R1, + E_CONTROLLER_DIGITAL_R2, + E_CONTROLLER_DIGITAL_UP, + E_CONTROLLER_DIGITAL_DOWN, + E_CONTROLLER_DIGITAL_LEFT, + E_CONTROLLER_DIGITAL_RIGHT, + E_CONTROLLER_DIGITAL_X, + E_CONTROLLER_DIGITAL_B, + E_CONTROLLER_DIGITAL_Y, + E_CONTROLLER_DIGITAL_A +} controller_digital_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define CONTROLLER_MASTER pros::E_CONTROLLER_MASTER +#define CONTROLLER_PARTNER pros::E_CONTROLLER_PARTNER +#define ANALOG_LEFT_X pros::E_CONTROLLER_ANALOG_LEFT_X +#define ANALOG_LEFT_Y pros::E_CONTROLLER_ANALOG_LEFT_Y +#define ANALOG_RIGHT_X pros::E_CONTROLLER_ANALOG_RIGHT_X +#define ANALOG_RIGHT_Y pros::E_CONTROLLER_ANALOG_RIGHT_Y +#define DIGITAL_L1 pros::E_CONTROLLER_DIGITAL_L1 +#define DIGITAL_L2 pros::E_CONTROLLER_DIGITAL_L2 +#define DIGITAL_R1 pros::E_CONTROLLER_DIGITAL_R1 +#define DIGITAL_R2 pros::E_CONTROLLER_DIGITAL_R2 +#define DIGITAL_UP pros::E_CONTROLLER_DIGITAL_UP +#define DIGITAL_DOWN pros::E_CONTROLLER_DIGITAL_DOWN +#define DIGITAL_LEFT pros::E_CONTROLLER_DIGITAL_LEFT +#define DIGITAL_RIGHT pros::E_CONTROLLER_DIGITAL_RIGHT +#define DIGITAL_X pros::E_CONTROLLER_DIGITAL_X +#define DIGITAL_B pros::E_CONTROLLER_DIGITAL_B +#define DIGITAL_Y pros::E_CONTROLLER_DIGITAL_Y +#define DIGITAL_A pros::E_CONTROLLER_DIGITAL_A +#else +#define CONTROLLER_MASTER E_CONTROLLER_MASTER +#define CONTROLLER_PARTNER E_CONTROLLER_PARTNER +#define ANALOG_LEFT_X E_CONTROLLER_ANALOG_LEFT_X +#define ANALOG_LEFT_Y E_CONTROLLER_ANALOG_LEFT_Y +#define ANALOG_RIGHT_X E_CONTROLLER_ANALOG_RIGHT_X +#define ANALOG_RIGHT_Y E_CONTROLLER_ANALOG_RIGHT_Y +#define DIGITAL_L1 E_CONTROLLER_DIGITAL_L1 +#define DIGITAL_L2 E_CONTROLLER_DIGITAL_L2 +#define DIGITAL_R1 E_CONTROLLER_DIGITAL_R1 +#define DIGITAL_R2 E_CONTROLLER_DIGITAL_R2 +#define DIGITAL_UP E_CONTROLLER_DIGITAL_UP +#define DIGITAL_DOWN E_CONTROLLER_DIGITAL_DOWN +#define DIGITAL_LEFT E_CONTROLLER_DIGITAL_LEFT +#define DIGITAL_RIGHT E_CONTROLLER_DIGITAL_RIGHT +#define DIGITAL_X E_CONTROLLER_DIGITAL_X +#define DIGITAL_B E_CONTROLLER_DIGITAL_B +#define DIGITAL_Y E_CONTROLLER_DIGITAL_Y +#define DIGITAL_A E_CONTROLLER_DIGITAL_A +#endif +#endif + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Checks if the controller is connected. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * + * \return 1 if the controller is connected, 0 otherwise + */ +int32_t controller_is_connected(controller_id_e_t id); + +/** + * Gets the value of an analog channel (joystick) on a controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param channel + * The analog channel to get. + * Must be one of ANALOG_LEFT_X, ANALOG_LEFT_Y, ANALOG_RIGHT_X, + * ANALOG_RIGHT_Y + * + * \return The current reading of the analog channel: [-127, 127]. + * If the controller was not connected, then 0 is returned + */ +int32_t controller_get_analog(controller_id_e_t id, controller_analog_e_t channel); + +/** + * Gets the battery capacity of the given controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER + * + * \return The controller's battery capacity + */ +int32_t controller_get_battery_capacity(controller_id_e_t id); + +/** + * Gets the battery level of the given controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER + * + * \return The controller's battery level + */ +int32_t controller_get_battery_level(controller_id_e_t id); + +/** + * Checks if a digital channel (button) on the controller is currently pressed. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param button + * The button to read. + * Must be one of DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is pressed. + * If the controller was not connected, then 0 is returned + */ +int32_t controller_get_digital(controller_id_e_t id, controller_digital_e_t button); + +/** + * Returns a rising-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under the + * same circumstances, so only one task should call this function for any given + * button. E.g., Task A calls this function for buttons 1 and 2. Task B may call + * this function for button 3, but should not for buttons 1 or 2. A typical + * use-case for this function is to call inside opcontrol to detect new button + * presses, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is pressed and had not been pressed + * the last time this function was called, 0 otherwise. + */ +int32_t controller_get_digital_new_press(controller_id_e_t id, controller_digital_e_t button); + +/** + * Sets text to the controller LCD screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param line + * The line number at which the text will be displayed [0-2] + * \param col + * The column number at which the text will be displayed [0-14] + * \param fmt + * The format string to print to the controller + * \param ... + * The argument list for the format string + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t controller_print(controller_id_e_t id, uint8_t line, uint8_t col, const char* fmt, ...); + +/** + * Sets text to the controller LCD screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param line + * The line number at which the text will be displayed [0-2] + * \param col + * The column number at which the text will be displayed [0-14] + * \param str + * The pre-formatted string to print to the controller + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t controller_set_text(controller_id_e_t id, uint8_t line, uint8_t col, const char* str); + +/** + * Clears an individual line of the controller screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param line + * The line number to clear [0-2] + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t controller_clear_line(controller_id_e_t id, uint8_t line); + +/** + * Clears all of the lines on the controller screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t controller_clear(controller_id_e_t id); + +/** + * Rumble the controller. + * + * \note Controller rumble activation is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A value other than E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER is + * given. + * EACCES - Another resource is currently trying to access the controller port. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + * \param rumble_pattern + * A string consisting of the characters '.', '-', and ' ', where dots + * are short rumbles, dashes are long rumbles, and spaces are pauses. + * Maximum supported length is 8 characters. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t controller_rumble(controller_id_e_t id, const char* rumble_pattern); + +/** + * Gets the current voltage of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current voltage of the battery + */ +int32_t battery_get_voltage(void); + +/** + * Gets the current current of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current current of the battery + */ +int32_t battery_get_current(void); + +/** + * Gets the current temperature of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current temperature of the battery + */ +double battery_get_temperature(void); + +/** + * Gets the current capacity of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current capacity of the battery + */ +double battery_get_capacity(void); + +#ifdef __cplusplus +} +} +} +#endif + +#endif // _PROS_MISC_H_ diff --git a/include/pros/misc.hpp b/include/pros/misc.hpp new file mode 100644 index 0000000..0e3b4d1 --- /dev/null +++ b/include/pros/misc.hpp @@ -0,0 +1,320 @@ +/** + * \file pros/misc.hpp + * + * Contains prototypes for miscellaneous functions pertaining to the controller, + * battery, and competition control. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/controller.html to + * learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reservered. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_MISC_HPP_ +#define _PROS_MISC_HPP_ + +#include "pros/misc.h" + +#include +#include + +namespace pros { +class Controller { + public: + /** + * Creates a controller object for the given controller id. + * + * \param id + * The ID of the controller (e.g. the master or partner controller). + * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER + */ + Controller(controller_id_e_t id); + + /** + * Checks if the controller is connected. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \return 1 if the controller is connected, 0 otherwise + */ + std::int32_t is_connected(void); + + /** + * Gets the value of an analog channel (joystick) on a controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param channel + * The analog channel to get. + * Must be one of ANALOG_LEFT_X, ANALOG_LEFT_Y, ANALOG_RIGHT_X, + * ANALOG_RIGHT_Y + * + * \return The current reading of the analog channel: [-127, 127]. + * If the controller was not connected, then 0 is returned + */ + std::int32_t get_analog(controller_analog_e_t channel); + + /** + * Gets the battery capacity of the controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \return The controller's battery capacity + */ + std::int32_t get_battery_capacity(void); + + /** + * Gets the battery level of the controller. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \return The controller's battery level + */ + std::int32_t get_battery_level(void); + + /** + * Checks if a digital channel (button) on the controller is currently + * pressed. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is pressed. + * If the controller was not connected, then 0 is returned + */ + std::int32_t get_digital(controller_digital_e_t button); + + /** + * Returns a rising-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. + * Task B may call this function for button 3, but should not for buttons + * 1 or 2. A typical use-case for this function is to call inside opcontrol + * to detect new button presses, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is pressed and had not been + * pressed the last time this function was called, 0 otherwise. + */ + std::int32_t get_digital_new_press(controller_digital_e_t button); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" + template + T convert_args(T arg) { + return arg; + } + const char* convert_args(const std::string& arg) { + return arg.c_str(); + } +#pragma GCC diagnostic pop + + /** + * Sets text to the controller LCD screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param line + * The line number at which the text will be displayed [0-2] + * \param col + * The column number at which the text will be displayed [0-14] + * \param fmt + * The format string to print to the controller + * \param ... + * The argument list for the format string + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + template + std::int32_t print(std::uint8_t line, std::uint8_t col, const char* fmt, Params... args) { + return pros::c::controller_print(_id, line, col, fmt, convert_args(args)...); + } + + /** + * Sets text to the controller LCD screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param line + * The line number at which the text will be displayed [0-2] + * \param col + * The column number at which the text will be displayed [0-14] + * \param str + * The pre-formatted string to print to the controller + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_text(std::uint8_t line, std::uint8_t col, const char* str); + + /** + * Clears an individual line of the controller screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param line + * The line number to clear [0-2] + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t clear_line(std::uint8_t line); + + /** + * Rumble the controller. + * + * \note Controller rumble activation is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param rumble_pattern + * A string consisting of the characters '.', '-', and ' ', where dots + * are short rumbles, dashes are long rumbles, and spaces are pauses. + * Maximum supported length is 8 characters. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t rumble(const char* rumble_pattern); + + /** + * Clears all of the lines on the controller screen. + * + * \note Controller text setting is currently in beta, so continuous, fast + * updates will not work well. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t clear(void); + + private: + controller_id_e_t _id; +}; + +namespace battery { +/** + * Gets the current voltage of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current voltage of the battery + */ +double get_capacity(void); + +/** + * Gets the current current of the battery in milliamps, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current current of the battery + */ +int32_t get_current(void); + +/** + * Gets the current temperature of the battery, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current temperature of the battery + */ +double get_temperature(void); + +/** + * Gets the current capacity of the battery in millivolts, as reported by VEXos. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the battery port. + * + * \return The current capacity of the battery + */ +int32_t get_voltage(void); +} // namespace battery + +namespace competition { +/** + * Get the current status of the competition control. + * + * \return The competition control status as a mask of bits with + * COMPETITION_{ENABLED,AUTONOMOUS,CONNECTED}. + */ +std::uint8_t get_status(void); +std::uint8_t is_autonomous(void); +std::uint8_t is_connected(void); +std::uint8_t is_disabled(void); +} // namespace competition +} // namespace pros + +#endif // _PROS_MISC_HPP_ diff --git a/include/pros/motors.h b/include/pros/motors.h new file mode 100644 index 0000000..e96caa1 --- /dev/null +++ b/include/pros/motors.h @@ -0,0 +1,1101 @@ +/** + * \file pros/motors.h + * + * Contains prototypes for the V5 Motor-related functions. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/motors.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_MOTORS_H_ +#define _PROS_MOTORS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +namespace pros { +namespace c { +#endif + +/******************************************************************************/ +/** Motor movement functions **/ +/** **/ +/** These functions allow programmers to make motors move **/ +/******************************************************************************/ + +/** + * Sets the voltage for the motor from -127 to 127. + * + * This is designed to map easily to the input from the controller's analog + * stick for simple opcontrol use. The actual behavior of the motor is analogous + * to use of motor_move_voltage(), or motorSet() from the PROS 2 API. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param voltage + * The new motor voltage from -127 to 127 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_move(uint8_t port, int32_t voltage); + +/** + * Sets the target absolute position for the motor to move to. + * + * This movement is relative to the position of the motor when initialized or + * the position when it was most recently reset with motor_set_zero_position(). + * + * \note This function simply sets the target for the motor, it does not block + * program execution until the movement finishes. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param position + * The absolute position to move to in the motor's encoder units + * \param velocity + * The maximum allowable velocity for the movement in RPM + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_move_absolute(uint8_t port, const double position, const int32_t velocity); + +/** + * Sets the relative target position for the motor to move to. + * + * This movement is relative to the current position of the motor as given in + * motor_get_position(). Providing 10.0 as the position parameter would result + * in the motor moving clockwise 10 units, no matter what the current position + * is. + * + * \note This function simply sets the target for the motor, it does not block + * program execution until the movement finishes. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param position + * The relative position to move to in the motor's encoder units + * \param velocity + * The maximum allowable velocity for the movement in RPM + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_move_relative(uint8_t port, const double position, const int32_t velocity); + +/** + * Sets the velocity for the motor. + * + * This velocity corresponds to different actual speeds depending on the gearset + * used for the motor. This results in a range of +-100 for E_MOTOR_GEARSET_36, + * +-200 for E_MOTOR_GEARSET_18, and +-600 for E_MOTOR_GEARSET_6. The velocity + * is held with PID to ensure consistent speed, as opposed to setting the + * motor's voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_move_velocity(uint8_t port, const int32_t velocity); + +/** + * Sets the output voltage for the motor from -12000 to 12000 in millivolts + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param voltage + * The new voltage value from -12000 to 12000 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_move_voltage(uint8_t port, const int32_t voltage); + +/** + * Changes the output velocity for a profiled movement (motor_move_absolute or + * motor_move_relative). This will have no effect if the motor is not following + * a profiled movement. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_modify_profiled_velocity(uint8_t port, const int32_t velocity); + +/** + * Gets the target position set for the motor by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The target position in its encoder units or PROS_ERR_F if the + * operation failed, setting errno. + */ +double motor_get_target_position(uint8_t port); + +/** + * Gets the velocity commanded to the motor by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The commanded motor velocity from +-100, +-200, or +-600, or PROS_ERR + * if the operation failed, setting errno. + */ +int32_t motor_get_target_velocity(uint8_t port); + +/******************************************************************************/ +/** Motor telemetry functions **/ +/** **/ +/** These functions allow programmers to collect telemetry from motors **/ +/******************************************************************************/ + +/** + * Gets the actual velocity of the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation + * failed, setting errno. + */ +double motor_get_actual_velocity(uint8_t port); + +/** + * Gets the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's current in mA or PROS_ERR if the operation failed, + * setting errno. + */ +int32_t motor_get_current_draw(uint8_t port); + +/** + * Gets the direction of movement for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 for moving in the positive direction, -1 for moving in the + * negative direction, or PROS_ERR if the operation failed, setting errno. + */ +int32_t motor_get_direction(uint8_t port); + +/** + * Gets the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's efficiency in percent or PROS_ERR_F if the operation + * failed, setting errno. + */ +double motor_get_efficiency(uint8_t port); + +/** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the motor's current limit is being exceeded and 0 if the current + * limit is not exceeded, or PROS_ERR if the operation failed, setting errno. + */ +int32_t motor_is_over_current(uint8_t port); + +/** + * Checks if the motor's temperature is above its limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the temperature limit is exceeded and 0 if the the temperature + * is below the limit, or PROS_ERR if the operation failed, setting errno. + */ +int32_t motor_is_over_temp(uint8_t port); + +/** + * Checks if the motor is stopped. + * + * \note Although this function forwards data from the motor, the motor + * presently does not provide any value. This function returns PROS_ERR with + * errno set to ENOSYS. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR + * if the operation failed, setting errno + */ +int32_t motor_is_stopped(uint32_t port); + +/** + * Checks if the motor is at its zero position. + * + * \note Although this function forwards data from the motor, the motor + * presently does not provide any value. This function returns PROS_ERR with + * errno set to ENOSYS. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the motor is at zero absolute position, 0 if the motor has + * moved from its absolute zero, or PROS_ERR if the operation failed, + * setting errno + */ +int32_t motor_get_zero_position_flag(uint32_t port); + +#ifdef __cplusplus +} // namespace c +#endif + +typedef enum motor_fault_e { + E_MOTOR_FAULT_NO_FAULTS = 0x00, + E_MOTOR_FAULT_MOTOR_OVER_TEMP = 0x01, // Analogous to motor_is_over_temp() + E_MOTOR_FAULT_DRIVER_FAULT = 0x02, // Indicates a motor h-bridge fault + E_MOTOR_FAULT_OVER_CURRENT = 0x04, // Analogous to motor_is_over_current() + E_MOTOR_FAULT_DRV_OVER_CURRENT = 0x08 // Indicates an h-bridge over current +} motor_fault_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define MOTOR_FAULT_NO_FAULTS pros::E_MOTOR_FAULT_NO_FAULTS +#define MOTOR_FAULT_MOTOR_OVER_TEMP pros::E_MOTOR_FAULT_MOTOR_OVER_TEMP +#define MOTOR_FAULT_DRIVER_FAULT pros::E_MOTOR_FAULT_DRIVER_FAULT +#define MOTOR_FAULT_OVER_CURRENT pros::E_MOTOR_FAULT_DRV_OVER_CURRENT +#define MOTOR_FAULT_DRV_OVER_CURRENT pros::E_MOTOR_FAULT_DRV_OVER_CURRENT +#else +#define MOTOR_FAULT_NO_FAULTS E_MOTOR_FAULT_NO_FAULTS +#define MOTOR_FAULT_MOTOR_OVER_TEMP E_MOTOR_FAULT_MOTOR_OVER_TEMP +#define MOTOR_FAULT_DRIVER_FAULT E_MOTOR_FAULT_DRIVER_FAULT +#define MOTOR_FAULT_OVER_CURRENT E_MOTOR_FAULT_DRV_OVER_CURRENT +#define MOTOR_FAULT_DRV_OVER_CURRENT E_MOTOR_FAULT_DRV_OVER_CURRENT +#endif +#endif + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Gets the faults experienced by the motor. + * + * Compare this bitfield to the bitmasks in motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return A bitfield containing the motor's faults. + */ +uint32_t motor_get_faults(uint8_t port); + +#ifdef __cplusplus +} // namespace c +#endif + +typedef enum motor_flag_e { + E_MOTOR_FLAGS_NONE = 0x00, + E_MOTOR_FLAGS_BUSY = 0x01, // Cannot currently communicate to the motor + E_MOTOR_FLAGS_ZERO_VELOCITY = 0x02, // Analogous to motor_is_stopped() + E_MOTOR_FLAGS_ZERO_POSITION = 0x04 // Analogous to motor_get_zero_position_flag() +} motor_flag_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define MOTOR_FLAGS_NONE pros::E_MOTOR_FLAGS_NONE +#define MOTOR_FLAGS_BUSY pros::E_MOTOR_FLAGS_BUSY +#define MOTOR_FLAGS_ZERO_VELOCITY pros::E_MOTOR_FLAGS_ZERO_VELOCITY +#define MOTOR_FLAGS_ZERO_POSITION pros::E_MOTOR_FLAGS_ZERO_POSITION +#else +#define MOTOR_FLAGS_NONE E_MOTOR_FLAGS_NONE +#define MOTOR_FLAGS_BUSY E_MOTOR_FLAGS_BUSY +#define MOTOR_FLAGS_ZERO_VELOCITY E_MOTOR_FLAGS_ZERO_VELOCITY +#define MOTOR_FLAGS_ZERO_POSITION E_MOTOR_FLAGS_ZERO_POSITION +#endif +#endif + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Gets the flags set by the motor's operation. + * + * Compare this bitfield to the bitmasks in motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return A bitfield containing the motor's flags. + */ +uint32_t motor_get_flags(uint8_t port); + +/** + * Gets the raw encoder count of the motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param[in] timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \return The raw encoder count at the given timestamp or PROS_ERR if the + * operation failed. + */ +int32_t motor_get_raw_position(uint8_t port, uint32_t* const timestamp); + +/** + * Gets the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's absolute position in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + */ +double motor_get_position(uint8_t port); + +/** + * Gets the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + */ +double motor_get_power(uint8_t port); + +/** + * Gets the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the + * operation failed, setting errno. + */ +double motor_get_temperature(uint8_t port); + +/** + * Gets the torque generated by the motor in Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, + * setting errno. + */ +double motor_get_torque(uint8_t port); + +/** + * Gets the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, + * setting errno. + */ +int32_t motor_get_voltage(uint8_t port); + +/******************************************************************************/ +/** Motor configuration functions **/ +/** **/ +/** These functions allow programmers to configure the behavior of motors **/ +/******************************************************************************/ + +#ifdef __cplusplus +} // namespace c +#endif + +/** + * Indicates the current 'brake mode' of a motor. + */ +typedef enum motor_brake_mode_e { + E_MOTOR_BRAKE_COAST = 0, // Motor coasts when stopped, traditional behavior + E_MOTOR_BRAKE_BRAKE = 1, // Motor brakes when stopped + E_MOTOR_BRAKE_HOLD = 2, // Motor actively holds position when stopped + E_MOTOR_BRAKE_INVALID = INT32_MAX +} motor_brake_mode_e_t; + +/** + * Indicates the units used by the motor encoders. + */ +typedef enum motor_encoder_units_e { + E_MOTOR_ENCODER_DEGREES = 0, // Position is recorded as angle in degrees + // as a floating point number + E_MOTOR_ENCODER_ROTATIONS = 1, // Position is recorded as angle in rotations + // as a floating point number + E_MOTOR_ENCODER_COUNTS = 2, // Position is recorded as raw encoder ticks + // as a whole number + E_MOTOR_ENCODER_INVALID = INT32_MAX +} motor_encoder_units_e_t; + +/** + * Indicates the current internal gear ratio of a motor. + */ +typedef enum motor_gearset_e { + E_MOTOR_GEARSET_36 = 0, // 36:1, 100 RPM, Red gear set + E_MOTOR_GEARSET_18 = 1, // 18:1, 200 RPM, Green gear set + E_MOTOR_GEARSET_06 = 2, // 6:1, 600 RPM, Blue gear set + E_MOTOR_GEARSET_INVALID = INT32_MAX +} motor_gearset_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define MOTOR_BRAKE_COAST pros::E_MOTOR_BRAKE_COAST +#define MOTOR_BRAKE_BRAKE pros::E_MOTOR_BRAKE_BRAKE +#define MOTOR_BRAKE_HOLD pros::E_MOTOR_BRAKE_HOLD +#define MOTOR_BRAKE_INVALID pros::E_MOTOR_BRAKE_INVALID +#define MOTOR_ENCODER_DEGREES pros::E_MOTOR_ENCODER_DEGREES +#define MOTOR_ENCODER_ROTATIONS pros::E_MOTOR_ENCODER_ROTATIONS +#define MOTOR_ENCODER_COUNTS pros::E_MOTOR_ENCODER_COUNTS +#define MOTOR_ENCODER_INVALID pros::E_MOTOR_ENCODER_INVALID +#define MOTOR_GEARSET_36 pros::E_MOTOR_GEARSET_36 +#define MOTOR_GEARSET_18 pros::E_MOTOR_GEARSET_18 +#define MOTOR_GEARSET_06 pros::E_MOTOR_GEARSET_06 +#define MOTOR_GEARSET_6 pros::E_MOTOR_GEARSET_06 +#define MOTOR_GEARSET_INVALID pros::E_MOTOR_GEARSET_INVALID +#else +#define MOTOR_BRAKE_COAST E_MOTOR_BRAKE_COAST +#define MOTOR_BRAKE_BRAKE E_MOTOR_BRAKE_BRAKE +#define MOTOR_BRAKE_HOLD E_MOTOR_BRAKE_HOLD +#define MOTOR_BRAKE_INVALID E_MOTOR_BRAKE_INVALID +#define MOTOR_ENCODER_DEGREES E_MOTOR_ENCODER_DEGREES +#define MOTOR_ENCODER_ROTATIONS E_MOTOR_ENCODER_ROTATIONS +#define MOTOR_ENCODER_COUNTS E_MOTOR_ENCODER_COUNTS +#define MOTOR_ENCODER_INVALID E_MOTOR_ENCODER_INVALID +#define MOTOR_GEARSET_36 E_MOTOR_GEARSET_36 +#define MOTOR_GEARSET_18 E_MOTOR_GEARSET_18 +#define MOTOR_GEARSET_06 E_MOTOR_GEARSET_06 +#define MOTOR_GEARSET_6 E_MOTOR_GEARSET_06 +#define MOTOR_GEARSET_INVALID E_MOTOR_GEARSET_INVALID +#endif +#endif + +/** + * Holds the information about a Motor's position or velocity PID controls. + * + * These values are in 4.4 format, meaning that a value of 0x20 represents 2.0, + * 0x21 represents 2.0625, 0x22 represents 2.125, etc. + */ +typedef struct motor_pid_full_s { + uint8_t kf; // The feedforward constant + uint8_t kp; // The proportional constant + uint8_t ki; // The integral constants + uint8_t kd; // The derivative constant + uint8_t filter; // A constant used for filtering the profile acceleration + uint16_t limit; // The integral limit + uint8_t threshold; // The threshold for determining if a position movement has + // reached its goal. This has no effect for velocity PID + // calculations. + uint8_t loopspeed; // The rate at which the PID computation is run in ms +} motor_pid_full_s_t; + +/** + * Holds just the constants for a Motor's position or velocity PID controls. + * + * These values are in 4.4 format, meaning that a value of 0x20 represents 2.0, + * 0x21 represents 2.0625, 0x22 represents 2.125, etc. + */ +typedef struct motor_pid_s { + uint8_t kf; // The feedforward constant + uint8_t kp; // The proportional constant + uint8_t ki; // The integral constants + uint8_t kd; // The derivative constant +} motor_pid_s_t; + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Sets the position for the motor in its encoder units. + * + * This will be the future reference point for the motor's "absolute" position. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param position + * The new reference position in its encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_zero_position(uint8_t port, const double position); + +/** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_tare_position(uint8_t port); + +/** + * Sets one of motor_brake_mode_e_t to the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param mode + * The motor_brake_mode_e_t to set for the motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_brake_mode(uint8_t port, const motor_brake_mode_e_t mode); + +/** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param limit + * The new current limit in mA + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_current_limit(uint8_t port, const int32_t limit); + +/** + * Sets one of motor_encoder_units_e_t for the motor encoder. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param units + * The new motor encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_encoder_units(uint8_t port, const motor_encoder_units_e_t units); + +/** + * Sets one of motor_gearset_e_t for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param gearset + * The new motor gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_gearing(uint8_t port, const motor_gearset_e_t gearset); + +/** + * Takes in floating point values and returns a properly formatted pid struct. + * The motor_pid_s_t struct is in 4.4 format, i.e. 0x20 is 2.0, 0x21 is 2.0625, + * etc. + * This function will convert the floating point values to the nearest 4.4 + * value. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param kf + * The feedforward constant + * \param kp + * The proportional constant + * \param ki + * The integral constant + * \param kd + * The derivative constant + * + * \return A motor_pid_s_t struct formatted properly in 4.4. + */ +motor_pid_s_t motor_convert_pid(double kf, double kp, double ki, double kd); + +/** + * Takes in floating point values and returns a properly formatted pid struct. + * The motor_pid_s_t struct is in 4.4 format, i.e. 0x20 is 2.0, 0x21 is 2.0625, + * etc. + * This function will convert the floating point values to the nearest 4.4 + * value. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param kf + * The feedforward constant + * \param kp + * The proportional constant + * \param ki + * The integral constant + * \param kd + * The derivative constant + * \param filter + * A constant used for filtering the profile acceleration + * \param limit + * The integral limit + * \param threshold + * The threshold for determining if a position movement has reached its + * goal. This has no effect for velocity PID calculations. + * \param loopspeed + * The rate at which the PID computation is run in ms + * + * \return A motor_pid_s_t struct formatted properly in 4.4. + */ +motor_pid_full_s_t motor_convert_pid_full(double kf, double kp, double ki, double kd, double filter, double limit, + double threshold, double loopspeed); + +/** + * Sets one of motor_pid_s_t for the motor. This intended to just modify the + * main PID constants. + * + * Only non-zero values of the struct will change the existing motor constants. + * + * \note This feature is in beta, it is advised to use caution when modifying + * the PID values. The motor could be damaged by particularly large constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_pos_pid(uint8_t port, const motor_pid_s_t pid); + +/** + * Sets one of motor_pid_full_s_t for the motor. + * + * Only non-zero values of the struct will change the existing motor constants. + * + * \note This feature is in beta, it is advised to use caution when modifying + * the PID values. The motor could be damaged by particularly large constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_pos_pid_full(uint8_t port, const motor_pid_full_s_t pid); + +/** + * Sets one of motor_pid_s_t for the motor. This intended to just modify the + * main PID constants. + * + * Only non-zero values of the struct will change the existing motor constants. + * + * \note This feature is in beta, it is advised to use caution when modifying + * the PID values. The motor could be damaged by particularly large constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_vel_pid(uint8_t port, const motor_pid_s_t pid); + +/** + * Sets one of motor_pid_full_s_t for the motor. + * + * Only non-zero values of the struct will change the existing motor constants. + * + * \note This feature is in beta, it is advised to use caution when modifying + * the PID values. The motor could be damaged by particularly large constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_vel_pid_full(uint8_t port, const motor_pid_full_s_t pid); + +/** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param reverse + * True reverses the motor, false is default + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_reversed(uint8_t port, const bool reverse); + +/** + * Sets the voltage limit for the motor in Volts. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param limit + * The new voltage limit in Volts + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t motor_set_voltage_limit(uint8_t port, const int32_t limit); + +/** + * Gets the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return One of motor_brake_mode_e_t, according to what was set for the motor, + * or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + */ +motor_brake_mode_e_t motor_get_brake_mode(uint8_t port); + +/** + * Gets the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's current limit in mA or PROS_ERR if the operation failed, + * setting errno. + */ +int32_t motor_get_current_limit(uint8_t port); + +/** + * Gets the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return One of motor_encoder_units_e_t according to what is set for the motor + * or E_MOTOR_ENCODER_INVALID if the operation failed. + */ +motor_encoder_units_e_t motor_get_encoder_units(uint8_t port); + +/** + * Gets the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return One of motor_gearset_e_t according to what is set for the motor, + * or E_GEARSET_INVALID if the operation failed. + */ +motor_gearset_e_t motor_get_gearing(uint8_t port); + +/** + * Gets the position PID that was set for the motor. This function will return + * zero for all of the parameters if the motor_set_pos_pid() or + * motor_set_pos_pid_full() functions have not been used. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * Additionally, in an error state all values of the returned struct are set + * to their negative maximum values. + * + * \param port + * The V5 port number from 1-21 + * + * \return A motor_pid_full_s_t containing the position PID constants last set + * to the given motor + */ +motor_pid_full_s_t motor_get_pos_pid(uint8_t port); + +/** + * Gets the velocity PID that was set for the motor. This function will return + * zero for all of the parameters if the motor_set_vel_pid() or + * motor_set_vel_pid_full() functions have not been used. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * Additionally, in an error state all values of the returned struct are set + * to their negative maximum values. + * + * \param port + * The V5 port number from 1-21 + * + * \return A motor_pid_full_s_t containing the velocity PID constants last set + * to the given motor + */ +motor_pid_full_s_t motor_get_vel_pid(uint8_t port); + +/** + * Gets the operation direction of the motor as set by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the motor has been reversed and 0 if the motor was not reversed, + * or PROS_ERR if the operation failed, setting errno. + */ +int32_t motor_is_reversed(uint8_t port); + +/** + * Gets the voltage limit set by the user. + * + * Default value is 0V, which means that there is no software limitation imposed + * on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The motor's voltage limit in V or PROS_ERR if the operation failed, + * setting errno. + */ +int32_t motor_get_voltage_limit(uint8_t port); + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif + +#endif // _PROS_MOTORS_H_ diff --git a/include/pros/motors.hpp b/include/pros/motors.hpp new file mode 100644 index 0000000..40dac7d --- /dev/null +++ b/include/pros/motors.hpp @@ -0,0 +1,835 @@ +/** + * \file pros/motors.hpp + * + * Contains prototypes for the V5 Motor-related functions. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/motors.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * \copyright (c) 2017-2018, Purdue University ACM SIGBots. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_MOTORS_HPP_ +#define _PROS_MOTORS_HPP_ + +#include +#include "pros/motors.h" + +namespace pros { +class Motor { + public: + /** + * Creates a Motor object for the given port and specifications. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param gearset + * The motor's gearset + * \param reverse + * True reverses the motor, false is default + * \param encoder_units + * The motor's encoder units + */ + explicit Motor(const std::uint8_t port, const motor_gearset_e_t gearset, const bool reverse, + const motor_encoder_units_e_t encoder_units); + + explicit Motor(const std::uint8_t port, const motor_gearset_e_t gearset, const bool reverse); + + explicit Motor(const std::uint8_t port, const motor_gearset_e_t gearset); + + explicit Motor(const std::uint8_t port, const bool reverse); + + explicit Motor(const std::uint8_t port); + + /****************************************************************************/ + /** Motor movement functions **/ + /** **/ + /** These functions allow programmers to make motors move **/ + /****************************************************************************/ + /** + * Sets the voltage for the motor from -128 to 127. + * + * This is designed to map easily to the input from the controller's analog + * stick for simple opcontrol use. The actual behavior of the motor is + * analogous to use of pros::Motor::move(), or motorSet from the PROS 2 API. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param voltage + * The new motor voltage from -127 to 127 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t operator=(std::int32_t voltage) const; + + /** + * Sets the voltage for the motor from -127 to 127. + * + * This is designed to map easily to the input from the controller's analog + * stick for simple opcontrol use. The actual behavior of the motor is + * analogous to use of motor_move(), or motorSet() from the PROS 2 API. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param voltage + * The new motor voltage from -127 to 127 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t move(std::int32_t voltage) const; + + /** + * Sets the target absolute position for the motor to move to. + * + * This movement is relative to the position of the motor when initialized or + * the position when it was most recently reset with + * pros::Motor::set_zero_position(). + * + * \note This function simply sets the target for the motor, it does not block + * program execution until the movement finishes. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param position + * The absolute position to move to in the motor's encoder units + * \param velocity + * The maximum allowable velocity for the movement in RPM + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t move_absolute(const double position, const std::int32_t velocity) const; + + /** + * Sets the relative target position for the motor to move to. + * + * This movement is relative to the current position of the motor as given in + * pros::Motor::motor_get_position(). Providing 10.0 as the position parameter + * would result in the motor moving clockwise 10 units, no matter what the + * current position is. + * + * \note This function simply sets the target for the motor, it does not block + * program execution until the movement finishes. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param position + * The relative position to move to in the motor's encoder units + * \param velocity + * The maximum allowable velocity for the movement in RPM + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t move_relative(const double position, const std::int32_t velocity) const; + + /** + * Sets the velocity for the motor. + * + * This velocity corresponds to different actual speeds depending on the + * gearset used for the motor. This results in a range of +-100 for + * E_MOTOR_GEARSET_36, +-200 for E_MOTOR_GEARSET_18, and +-600 for + * E_MOTOR_GEARSET_6. The velocity is held with PID to ensure consistent + * speed, as opposed to setting the motor's voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param velocity + * The new motor velocity from -+-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t move_velocity(const std::int32_t velocity) const; + + /** + * Sets the output voltage for the motor from -12000 to 12000 in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param voltage + * The new voltage value from -12000 to 12000 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t move_voltage(const std::int32_t voltage) const; + + /** + * Changes the output velocity for a profiled movement (motor_move_absolute() + * or motor_move_relative()). This will have no effect if the motor is not + * following a profiled movement. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t modify_profiled_velocity(const std::int32_t velocity) const; + + /** + * Gets the target position set for the motor by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The target position in its encoder units or PROS_ERR_F if the + * operation failed, setting errno. + */ + virtual double get_target_position(void) const; + + /** + * Gets the velocity commanded to the motor by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The commanded motor velocity from +-100, +-200, or +-600, or + * PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t get_target_velocity(void) const; + + /****************************************************************************/ + /** Motor telemetry functions **/ + /** **/ + /** These functions allow programmers to collect telemetry from motors **/ + /****************************************************************************/ + + /** + * Gets the actual velocity of the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double get_actual_velocity(void) const; + + /** + * Gets the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's current in mA or PROS_ERR if the operation failed, + * setting errno. + */ + virtual std::int32_t get_current_draw(void) const; + + /** + * Gets the direction of movement for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 for moving in the positive direction, -1 for moving in the + * negative direction, and PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t get_direction(void) const; + + /** + * Gets the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's efficiency in percent or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double get_efficiency(void) const; + + /** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 if the motor's current limit is being exceeded and 0 if the + * current limit is not exceeded, or PROS_ERR if the operation failed, setting + * errno. + */ + virtual std::int32_t is_over_current(void) const; + + /** + * Checks if the motor is stopped. + * + * \note Although this function forwards data from the motor, the motor + * presently does not provide any value. This function returns PROS_ERR with + * errno set to ENOSYS. + * + * \return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR + * if the operation failed, setting errno + */ + virtual std::int32_t is_stopped(void) const; + + /** + * Checks if the motor is at its zero position. + * + * \note Although this function forwards data from the motor, the motor + * presently does not provide any value. This function returns PROS_ERR with + * errno set to ENOSYS. + * + * \return 1 if the motor is at zero absolute position, 0 if the motor has + * moved from its absolute zero, or PROS_ERR if the operation failed, setting + * errno + */ + virtual std::int32_t get_zero_position_flag(void) const; + + /** + * Gets the faults experienced by the motor. + * + * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return A bitfield containing the motor's faults. + */ + virtual std::uint32_t get_faults(void) const; + + /** + * Gets the flags set by the motor's operation. + * + * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return A bitfield containing the motor's flags. + */ + virtual std::uint32_t get_flags(void) const; + + /** + * Gets the raw encoder count of the motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param[in] timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \return The raw encoder count at the given timestamp or PROS_ERR if the + * operation failed. + */ + virtual std::int32_t get_raw_position(std::uint32_t* const timestamp) const; + + /** + * Gets the temperature limit flag for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 if the temperature limit is exceeded and 0 if the temperature is + * below the limit, or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t is_over_temp(void) const; + + /** + * Gets the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's absolute position in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + */ + virtual double get_position(void) const; + + /** + * Gets the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + */ + virtual double get_power(void) const; + + /** + * Gets the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the + * operation failed, setting errno. + */ + virtual double get_temperature(void) const; + + /** + * Gets the torque generated by the motor in Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual double get_torque(void) const; + + /** + * Gets the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, + * setting errno. + */ + virtual std::int32_t get_voltage(void) const; + + /****************************************************************************/ + /** Motor configuration functions **/ + /** **/ + /** These functions allow programmers to configure the behavior of motors **/ + /****************************************************************************/ + + /** + * Sets the position for the motor in its encoder units. + * + * This will be the future reference point for the motor's "absolute" + * position. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param position + * The new reference position in its encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_zero_position(const double position) const; + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t tare_position(void) const; + + /** + * Sets one of motor_brake_mode_e_t to the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param mode + * The motor_brake_mode_e_t to set for the motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_brake_mode(const motor_brake_mode_e_t mode) const; + + /** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param limit + * The new current limit in mA + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_current_limit(const std::int32_t limit) const; + + /** + * Sets one of motor_encoder_units_e_t for the motor encoder. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param units + * The new motor encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_encoder_units(const motor_encoder_units_e_t units) const; + + /** + * Sets one of motor_gearset_e_t for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param gearset + * The new motor gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_gearing(const motor_gearset_e_t gearset) const; + + /** + * Takes in floating point values and returns a properly formatted pid struct. + * The motor_pid_s_t struct is in 4.4 format, i.e. 0x20 is 2.0, 0x21 is + * 2.0625, etc. + * This function will convert the floating point values to the nearest 4.4 + * value. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param kf + * The feedforward constant + * \param kp + * The proportional constant + * \param ki + * The integral constant + * \param kd + * The derivative constant + * + * \return A motor_pid_s_t struct formatted properly in 4.4. + */ + static motor_pid_s_t convert_pid(double kf, double kp, double ki, double kd); + + /** + * Takes in floating point values and returns a properly formatted pid struct. + * The motor_pid_s_t struct is in 4.4 format, i.e. 0x20 is 2.0, 0x21 is + * 2.0625, etc. + * This function will convert the floating point values to the nearest 4.4 + * value. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param kf + * The feedforward constant + * \param kp + * The proportional constant + * \param ki + * The integral constant + * \param kd + * The derivative constant + * \param filter + * A constant used for filtering the profile acceleration + * \param limit + * The integral limit + * \param threshold + * The threshold for determining if a position movement has reached its + * goal. This has no effect for velocity PID calculations. + * \param loopspeed + * The rate at which the PID computation is run in ms + * + * \return A motor_pid_s_t struct formatted properly in 4.4. + */ + static motor_pid_full_s_t convert_pid_full(double kf, double kp, double ki, double kd, double filter, double limit, + double threshold, double loopspeed); + + /** + * Sets one of motor_pid_s_t for the motor. This intended to just modify the + * main PID constants. + * + * Only non-zero values of the struct will change the existing motor + * constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_pos_pid(const motor_pid_s_t pid) const; + + /** + * Sets one of motor_pid_full_s_t for the motor. + * + * Only non-zero values of the struct will change the existing motor + * constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_pos_pid_full(const motor_pid_full_s_t pid) const; + + /** + * Sets one of motor_pid_s_t for the motor. This intended to just modify the + * main PID constants. + * + * Only non-zero values of the struct will change the existing motor + * constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_vel_pid(const motor_pid_s_t pid) const; + + /** + * Sets one of motor_pid_full_s_t for the motor. + * + * Only non-zero values of the struct will change the existing motor + * constants. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param pid + * The new motor PID constants + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_vel_pid_full(const motor_pid_full_s_t pid) const; + + /** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param reverse + * True reverses the motor, false is default + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_reversed(const bool reverse) const; + + /** + * Sets the voltage limit for the motor in Volts. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param limit + * The new voltage limit in Volts + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + virtual std::int32_t set_voltage_limit(const std::int32_t limit) const; + + /** + * Gets the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return One of motor_brake_mode_e_t, according to what was set for the + * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + */ + virtual motor_brake_mode_e_t get_brake_mode(void) const; + + /** + * Gets the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's current limit in mA or PROS_ERR if the operation failed, + * setting errno. + */ + virtual std::int32_t get_current_limit(void) const; + + /** + * Gets the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return One of motor_encoder_units_e_t according to what is set for the + * motor or E_MOTOR_ENCODER_INVALID if the operation failed. + */ + virtual motor_encoder_units_e_t get_encoder_units(void) const; + + /** + * Gets the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return One of motor_gearset_e_t according to what is set for the motor, + * or E_GEARSET_INVALID if the operation failed. + */ + virtual motor_gearset_e_t get_gearing(void) const; + + /** + * Gets the position PID that was set for the motor. This function will return + * zero for all of the parameters if the motor_set_pos_pid() or + * motor_set_pos_pid_full() functions have not been used. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * Additionally, in an error state all values of the returned struct are set + * to their negative maximum values. + * + * \return A motor_pid_full_s_t containing the position PID constants last set + * to the given motor + */ + virtual motor_pid_full_s_t get_pos_pid(void) const; + + /** + * Gets the velocity PID that was set for the motor. This function will return + * zero for all of the parameters if the motor_set_vel_pid() or + * motor_set_vel_pid_full() functions have not been used. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * Additionally, in an error state all values of the returned struct are set + * to their negative maximum values. + * + * \return A motor_pid_full_s_t containing the velocity PID constants last set + * to the given motor + */ + virtual motor_pid_full_s_t get_vel_pid(void) const; + + /** + * Gets the operation direction of the motor as set by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 if the motor has been reversed and 0 if the motor was not + * reversed, or PROS_ERR if the operation failed, setting errno. + */ + virtual std::int32_t is_reversed(void) const; + + /** + * Gets the voltage limit set by the user. + * + * Default value is 0V, which means that there is no software limitation + * imposed on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The motor's voltage limit in V or PROS_ERR if the operation failed, + * setting errno. + */ + virtual std::int32_t get_voltage_limit(void) const; + + private: + const std::uint8_t _port; +}; + +namespace literals { +const pros::Motor operator"" _mtr(const unsigned long long int m); +const pros::Motor operator"" _rmtr(const unsigned long long int m); +} // namespace literals +} // namespace pros +#endif // _PROS_MOTORS_HPP_ diff --git a/include/pros/rtos.h b/include/pros/rtos.h new file mode 100644 index 0000000..944ad34 --- /dev/null +++ b/include/pros/rtos.h @@ -0,0 +1,411 @@ +/** + * \file pros/rtos.h + * + * Contains declarations for the PROS RTOS kernel for use by typical VEX + * programmers. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html to + * learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_RTOS_H_ +#define _PROS_RTOS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif + +// The highest priority that can be assigned to a task. Beware of deadlock. +#define TASK_PRIORITY_MAX 16 + +// The lowest priority that can be assigned to a task. +// This may cause severe performance problems and is generally not recommended. +#define TASK_PRIORITY_MIN 1 + +// The default task priority, which should be used for most tasks. +// Default tasks such as autonomous() inherit this priority. +#define TASK_PRIORITY_DEFAULT 8 + +// The recommended stack size for a new task. This stack size is used for +// default tasks such as autonomous(). This equates to 32,768 bytes, or 128 +// times the default stack size for a task in PROS 2. +#define TASK_STACK_DEPTH_DEFAULT 0x2000 + +// The minimal stack size for a task. This equates to 2048 bytes, or 8 times the +// default stack size for a task in PROS 2. +#define TASK_STACK_DEPTH_MIN 0x200 + +// The maximum number of characters allowed in a task's name. +#define TASK_NAME_MAX_LEN 32 + +// The maximum timeout value that can be given to, for instance, a mutex grab. +#define TIMEOUT_MAX ((uint32_t)0xffffffffUL) + +typedef void* task_t; +typedef void (*task_fn_t)(void*); + +typedef enum { + E_TASK_STATE_RUNNING = 0, + E_TASK_STATE_READY, + E_TASK_STATE_BLOCKED, + E_TASK_STATE_SUSPENDED, + E_TASK_STATE_DELETED, + E_TASK_STATE_INVALID +} task_state_e_t; + +typedef enum { + E_NOTIFY_ACTION_NONE, + E_NOTIFY_ACTION_BITS, + E_NOTIFY_ACTION_INCR, + E_NOTIFY_ACTION_OWRITE, + E_NOTIFY_ACTION_NO_OWRITE +} notify_action_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define TASK_STATE_RUNNING pros::E_TASK_STATE_RUNNING +#define TASK_STATE_READY pros::E_TASK_STATE_READY +#define TASK_STATE_BLOCKED pros::E_TASK_STATE_BLOCKED +#define TASK_STATE_SUSPENDED pros::E_TASK_STATE_SUSPENDED +#define TASK_STATE_DELETED pros::E_TASK_STATE_DELETED +#define TASK_STATE_INVALID pros::E_TASK_STATE_INVALID +#define NOTIFY_ACTION_NONE pros::E_NOTIFY_ACTION_NONE +#define NOTIFY_ACTION_BITS pros::E_NOTIFY_ACTION_BITS +#define NOTIFY_ACTION_INCR pros::E_NOTIFY_ACTION_INCR +#define NOTIFY_ACTION_OWRITE pros::E_NOTIFY_ACTION_OWRITE +#define NOTIFY_ACTION_NO_OWRITE pros::E_NOTIFY_ACTION_NO_OWRITE +#else +#define TASK_STATE_RUNNING E_TASK_STATE_RUNNING +#define TASK_STATE_READY E_TASK_STATE_READY +#define TASK_STATE_BLOCKED E_TASK_STATE_BLOCKED +#define TASK_STATE_SUSPENDED E_TASK_STATE_SUSPENDED +#define TASK_STATE_DELETED E_TASK_STATE_DELETED +#define TASK_STATE_INVALID E_TASK_STATE_INVALID +#define NOTIFY_ACTION_NONE E_NOTIFY_ACTION_NONE +#define NOTIFY_ACTION_BITS E_NOTIFY_ACTION_BITS +#define NOTIFY_ACTION_INCR E_NOTIFY_ACTION_INCR +#define NOTIFY_ACTION_OWRITE E_NOTIFY_ACTION_OWRITE +#define NOTIFY_ACTION_NO_OWRITE E_NOTIFY_ACTION_NO_OWRITE +#endif +#endif + +typedef void* mutex_t; + +/** + * Refers to the current task handle + */ +#ifdef __cplusplus +#define CURRENT_TASK ((pros::task_t)NULL) +#else +#define CURRENT_TASK ((task_t)NULL) +#endif + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Gets the number of milliseconds since PROS initialized. + * + * \return The number of milliseconds since PROS initialized + */ +uint32_t millis(void); + +/** + * Creates a new task and add it to the list of tasks that are ready to run. + * + * This function uses the following values of errno when an error state is + * reached: + * ENOMEM - The stack cannot be used as the TCB was not created. + * + * \param function + * Pointer to the task entry function + * \param parameters + * Pointer to memory that will be used as a parameter for the task being + * created. This memory should not typically come from stack, but rather + * from dynamically (i.e., malloc'd) or statically allocated memory. + * \param prio + * The priority at which the task should run. + * TASK_PRIO_DEFAULT plus/minus 1 or 2 is typically used. + * \param stack_depth + * The number of words (i.e. 4 * stack_depth) available on the task's + * stack. TASK_STACK_DEPTH_DEFAULT is typically sufficienct. + * \param name + * A descriptive name for the task. This is mainly used to facilitate + * debugging. The name may be up to 32 characters long. + * + * \return A handle by which the newly created task can be referenced. If an + * error occurred, NULL will be returned and errno can be checked for hints as + * to why task_create failed. + */ +task_t task_create(task_fn_t function, void* const parameters, uint32_t prio, const uint16_t stack_depth, + const char* const name); + +/** + * Removes a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * Memory dynamically allocated by the task is not automatically freed, and + * should be freed before the task is deleted. + * + * \param task + * The handle of the task to be deleted. Passing NULL will cause the + * calling task to be deleted. + */ +void task_delete(task_t task); + +/** + * Delays a task for a given number of milliseconds. + * + * This is not the best method to have a task execute code at predefined + * intervals, as the delay time is measured from when the delay is requested. + * To delay cyclically, use task_delay_until(). + * + * \param milliseconds + * The number of milliseconds to wait (1000 milliseconds per second) + */ +void task_delay(const uint32_t milliseconds); + +void delay(const uint32_t milliseconds); + +/** + * Delays a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * The task will be woken up at the time *prev_time + delta, and *prev_time will + * be updated to reflect the time at which the task will unblock. + * + * \param prev_time + * A pointer to the location storing the setpoint time. This should + * typically be initialized to the return value of millis(). + * \param delta + * The number of milliseconds to wait (1000 milliseconds per second) + */ +void task_delay_until(uint32_t* const prev_time, const uint32_t delta); + +/** + * Gets the priority of the specified task. + * + * \param task + * The task to check + * + * \return The priority of the task + */ +uint32_t task_get_priority(task_t task); + +/** + * Sets the priority of the specified task. + * + * If the specified task's state is available to be scheduled (e.g. not blocked) + * and new priority is higher than the currently running task, a context switch + * may occur. + * + * \param task + * The task to set + * \param prio + * The new priority of the task + */ +void task_set_priority(task_t task, uint32_t prio); + +/** + * Gets the state of the specified task. + * + * \param task + * The task to check + * + * \return The state of the task + */ +task_state_e_t task_get_state(task_t task); + +/** + * Suspends the specified task, making it ineligible to be scheduled. + * + * \param task + * The task to suspend + */ +void task_suspend(task_t task); + +/** + * Resumes the specified task, making it eligible to be scheduled. + * + * \param task + * The task to resume + */ +void task_resume(task_t task); + +/** + * Gets the number of tasks the kernel is currently managing, including all + * ready, blocked, or suspended tasks. A task that has been deleted, but not yet + * reaped by the idle task will also be included in the count. Tasks recently + * created may take one context switch to be counted. + * + * \return The number of tasks that are currently being managed by the kernel. + */ +uint32_t task_get_count(void); + +/** + * Gets the name of the specified task. + * + * \param task + * The task to check + * + * \return A pointer to the name of the task + */ +char* task_get_name(task_t task); + +/** + * Gets a task handle from the specified name + * + * The operation takes a relatively long time and should be used sparingly. + * + * \param name + * The name to query + * + * \return A task handle with a matching name, or NULL if none were found. + */ +task_t task_get_by_name(const char* name); + +/** + * Get the currently running task handle. This could be useful if a task + * wants to tell another task about itself. + * + * \return The currently running task handle. + */ +task_t task_get_current(); + +/** + * Sends a simple notification to task and increments the notification counter. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param task + * The task to notify + * + * \return Always returns true. + */ +uint32_t task_notify(task_t task); + +/** + * Sends a notification to a task, optionally performing some action. Will also + * retrieve the value of the notification in the target task before modifying + * the notification value. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param task + * The task to notify + * \param value + * The value used in performing the action + * \param action + * An action to optionally perform on the receiving task's notification + * value + * \param prev_value + * A pointer to store the previous value of the target task's + * notification, may be NULL + * + * \return Dependent on the notification action. + * For NOTIFY_ACTION_NO_WRITE: return 0 if the value could be written without + * needing to overwrite, 1 otherwise. + * For all other NOTIFY_ACTION values: always return 0 + */ +uint32_t task_notify_ext(task_t task, uint32_t value, notify_action_e_t action, uint32_t* prev_value); + +/** + * Waits for a notification to be nonzero. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param clear_on_exit + * If true (1), then the notification value is cleared. + * If false (0), then the notification value is decremented. + * \param timeout + * Specifies the amount of time to be spent waiting for a notification + * to occur. + * + * \return The value of the task's notification value before it is decremented + * or cleared + */ +uint32_t task_notify_take(bool clear_on_exit, uint32_t timeout); + +/** + * Clears the notification for a task. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param task + * The task to clear + * + * \return False if there was not a notification waiting, true if there was + */ +bool task_notify_clear(task_t task); + +/** + * Creates a mutex. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \return A handle to a newly created mutex. If an error occurred, NULL will be + * returned and errno can be checked for hints as to why mutex_create failed. + */ +mutex_t mutex_create(void); + +/** + * Takes and locks a mutex, waiting for up to a certain number of milliseconds + * before timing out. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \param mutex + * Mutex to attempt to lock. + * \param timeout + * Time to wait before the mutex becomes available. A timeout of 0 can + * be used to poll the mutex. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the mutex was successfully taken, false otherwise. If false + * is returned, then errno is set with a hint about why the the mutex + * couldn't be taken. + */ +bool mutex_take(mutex_t mutex, uint32_t timeout); + +/** + * Unlocks a mutex. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \param mutex + * Mutex to unlock. + * + * \return True if the mutex was successfully returned, false otherwise. If + * false is returned, then errno is set with a hint about why the mutex + * couldn't be returned. + */ +bool mutex_give(mutex_t mutex); + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif + +#endif // _PROS_RTOS_H_ diff --git a/include/pros/rtos.hpp b/include/pros/rtos.hpp new file mode 100644 index 0000000..493f8c2 --- /dev/null +++ b/include/pros/rtos.hpp @@ -0,0 +1,308 @@ +/** + * \file pros/rtos.hpp + * + * Contains declarations for the PROS RTOS kernel for use by typical VEX + * programmers. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html to + * learn more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_RTOS_HPP_ +#define _PROS_RTOS_HPP_ + +#include "pros/rtos.h" +#undef delay +#include +#include + +namespace pros { +class Task { + public: + /** + * Creates a new task and add it to the list of tasks that are ready to run. + * + * This function uses the following values of errno when an error state is + * reached: + * ENOMEM - The stack cannot be used as the TCB was not created. + * + * \param function + * Pointer to the task entry function + * \param parameters + * Pointer to memory that will be used as a parameter for the task + * being created. This memory should not typically come from stack, + * but rather from dynamically (i.e., malloc'd) or statically + * allocated memory. + * \param prio + * The priority at which the task should run. + * TASK_PRIO_DEFAULT plus/minus 1 or 2 is typically used. + * \param stack_depth + * The number of words (i.e. 4 * stack_depth) available on the task's + * stack. TASK_STACK_DEPTH_DEFAULT is typically sufficienct. + * \param name + * A descriptive name for the task. This is mainly used to facilitate + * debugging. The name may be up to 32 characters long. + * + */ + Task(task_fn_t function, void* parameters = NULL, std::uint32_t prio = TASK_PRIORITY_DEFAULT, + std::uint16_t stack_depth = TASK_STACK_DEPTH_DEFAULT, const char* name = ""); + /** + * Create a C++ task object from a task handle + * + * \param task + * A task handle from task_create() for which to create a pros::Task + * object. + */ + Task(task_t task); + + /** + * Get the currently running Task + */ + static Task current(); + + /** + * Creates a new task and add it to the list of tasks that are ready to run. + * + * \param in + * A task handle from task_create() for which to create a pros::Task + * object. + */ + void operator=(const task_t in); + + /** + * Removes the Task from the RTOS real time kernel's management. This task + * will be removed from all ready, blocked, suspended and event lists. + * + * Memory dynamically allocated by the task is not automatically freed, and + * should be freed before the task is deleted. + */ + void remove(); + + /** + * Gets the priority of the specified task. + * + * \return The priority of the task + */ + std::uint32_t get_priority(void); + + /** + * Sets the priority of the specified task. + * + * If the specified task's state is available to be scheduled (e.g. not + * blocked) and new priority is higher than the currently running task, + * a context switch may occur. + * + * \param prio + * The new priority of the task + */ + void set_priority(std::uint32_t prio); + + /** + * Gets the state of the specified task. + * + * \return The state of the task + */ + std::uint32_t get_state(void); + + /** + * Suspends the specified task, making it ineligible to be scheduled. + */ + void suspend(void); + + /** + * Resumes the specified task, making it eligible to be scheduled. + * + * \param task + * The task to resume + */ + void resume(void); + + /** + * Gets the name of the specified task. + * + * \return A pointer to the name of the task + */ + const char* get_name(void); + + /** + * Convert this object to a C task_t handle + */ + operator task_t() { + return task; + } + + /** + * Sends a simple notification to task and increments the notification + * counter. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \return Always returns true. + */ + std::uint32_t notify(void); + + /** + * Sends a notification to a task, optionally performing some action. Will + * also retrieve the value of the notification in the target task before + * modifying the notification value. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param value + * The value used in performing the action + * \param action + * An action to optionally perform on the receiving task's notification + * value + * \param prev_value + * A pointer to store the previous value of the target task's + * notification, may be NULL + * + * \return Dependent on the notification action. + * For NOTIFY_ACTION_NO_WRITE: return 0 if the value could be written without + * needing to overwrite, 1 otherwise. + * For all other NOTIFY_ACTION values: always return 0 + */ + std::uint32_t notify_ext(std::uint32_t value, notify_action_e_t action, std::uint32_t* prev_value); + + /** + * Waits for a notification to be nonzero. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \param clear_on_exit + * If true (1), then the notification value is cleared. + * If false (0), then the notification value is decremented. + * \param timeout + * Specifies the amount of time to be spent waiting for a notification + * to occur. + * + * \return The value of the task's notification value before it is decremented + * or cleared + */ + std::uint32_t notify_take(bool clear_on_exit, std::uint32_t timeout); + + /** + * Clears the notification for a task. + * + * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for + * details. + * + * \return False if there was not a notification waiting, true if there was + */ + bool notify_clear(void); + + /** + * Delays a task for a given number of milliseconds. + * + * This is not the best method to have a task execute code at predefined + * intervals, as the delay time is measured from when the delay is requested. + * To delay cyclically, use task_delay_until(). + * + * \param milliseconds + * The number of milliseconds to wait (1000 milliseconds per second) + */ + static void delay(const std::uint32_t milliseconds); + + /** + * Delays a task until a specified time. This function can be used by + * periodic tasks to ensure a constant execution frequency. + * + * The task will be woken up at the time *prev_time + delta, and *prev_time + * will be updated to reflect the time at which the task will unblock. + * + * \param prev_time + * A pointer to the location storing the setpoint time. This should + * typically be initialized to the return value from pros::millis(). + * \param delta + * The number of milliseconds to wait (1000 milliseconds per second) + */ + static void delay_until(std::uint32_t* const prev_time, const std::uint32_t delta); + + /** + * Gets the number of tasks the kernel is currently managing, including all + * ready, blocked, or suspended tasks. A task that has been deleted, but not + * yet reaped by the idle task will also be included in the count. + * Tasks recently created may take one context switch to be counted. + * + * \return The number of tasks that are currently being managed by the kernel. + */ + static std::uint32_t get_count(void); + + private: + task_t task; +}; + +class Mutex { + public: + Mutex(void); + + /** + * Takes and locks a mutex, waiting for up to a certain number of milliseconds + * before timing out. + * + * See + * https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \param timeout + * Time to wait before the mutex becomes available. A timeout of 0 can + * be used to poll the mutex. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the mutex was successfully taken, false otherwise. If false + * is returned, then errno is set with a hint about why the the mutex + * couldn't be taken. + */ + bool take(std::uint32_t timeout); + + /** + * Unlocks a mutex. + * + * See + * https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \return True if the mutex was successfully returned, false otherwise. If + * false is returned, then errno is set with a hint about why the mutex + * couldn't be returned. + */ + bool give(void); + + private: + mutex_t mutex; +}; + +/** + * Gets the number of milliseconds since PROS initialized. + * + * \return The number of milliseconds since PROS initialized + */ +using pros::c::millis; + +/** + * Delays a task for a given number of milliseconds. + * + * This is not the best method to have a task execute code at predefined + * intervals, as the delay time is measured from when the delay is requested. + * To delay cyclically, use task_delay_until(). + * + * \param milliseconds + * The number of milliseconds to wait (1000 milliseconds per second) + */ +using pros::c::delay; +} // namespace pros + +#endif // _PROS_RTOS_HPP_s diff --git a/include/pros/vision.h b/include/pros/vision.h new file mode 100644 index 0000000..ad58d09 --- /dev/null +++ b/include/pros/vision.h @@ -0,0 +1,555 @@ +/** + * \file pros/vision.h + * + * Contains prototypes for the VEX Vision Sensor-related functions. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_VISION_H_ +#define _PROS_VISION_H_ + +#define VISION_OBJECT_ERR_SIG 255 +// Parameters given by VEX +#define VISION_FOV_WIDTH 316 +#define VISION_FOV_HEIGHT 212 + +#include + +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif +/** + * This enumeration defines the different types of objects + * that can be detected by the Vision Sensor + */ +typedef enum vision_object_type { + E_VISION_OBJECT_NORMAL = 0, + E_VISION_OBJECT_COLOR_CODE = 1, + E_VISION_OBJECT_LINE = 2 +} vision_object_type_e_t; + +/** + * This structure contains the parameters used by the Vision Sensor + * to detect objects. + */ +typedef struct __attribute__((__packed__)) vision_signature { + uint8_t id; + uint8_t _pad[3]; + float range; + int32_t u_min; + int32_t u_max; + int32_t u_mean; + int32_t v_min; + int32_t v_max; + int32_t v_mean; + uint32_t rgb; + uint32_t type; +} vision_signature_s_t; + +/** + * Color codes are just signatures with multiple IDs and a different type. + */ +typedef uint16_t vision_color_code_t; + +/** + * This structure contains a descriptor of an object detected + * by the Vision Sensor + */ +typedef struct __attribute__((__packed__)) vision_object { + // Object signature + uint16_t signature; + // Object type, e.g. normal, color code, or line detection + vision_object_type_e_t type; + // left boundary coordinate of the object + int16_t left_coord; + // top boundary coordinate of the object + int16_t top_coord; + // width of the object + int16_t width; + // height of the object + int16_t height; + // Angle of a color code object in 0.1 degree units (e.g. 10 -> 1 degree, 155 + // -> 15.5 degrees) + uint16_t angle; + + // coordinates of the middle of the object (computed from the values above) + int16_t x_middle_coord; + int16_t y_middle_coord; +} vision_object_s_t; + +typedef enum vision_zero { + E_VISION_ZERO_TOPLEFT = 0, // (0,0) coordinate is the top left of the FOV + E_VISION_ZERO_CENTER = 1 // (0,0) coordinate is the center of the FOV +} vision_zero_e_t; + +#ifdef PROS_USE_SIMPLE_NAMES +#ifdef __cplusplus +#define VISION_OBJECT_NORMAL pros::E_VISION_OBJECT_NORMAL +#define VISION_OBJECT_COLOR_CODE pros::E_VISION_OBJECT_COLOR_CODE +#define VISION_OBJECT_LINE pros::E_VISION_OBJECT_LINE +#define VISION_ZERO_TOPLEFT pros::E_VISION_ZERO_TOPLEFT +#define VISION_ZERO_CENTER pros::E_VISION_ZERO_CENTER +#else +#define VISION_OBJECT_NORMAL E_VISION_OBJECT_NORMAL +#define VISION_OBJECT_COLOR_CODE E_VISION_OBJECT_COLOR_CODE +#define VISION_OBJECT_LINE E_VISION_OBJECT_LINE +#define VISION_ZERO_TOPLEFT E_VISION_ZERO_TOPLEFT +#define VISION_ZERO_CENTER E_VISION_ZERO_CENTER +#endif +#endif + +#ifdef __cplusplus +namespace c { +#endif + +/** + * Clears the vision sensor LED color, reseting it back to its default behavior, + * displaying the most prominent object signature color. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_clear_led(uint8_t port); + +/** + * Creates a signature from the vision sensor utility + * + * \param id + * The signature ID + * \param u_min + * Minimum value on U axis + * \param u_max + * Maximum value on U axis + * \param u_mean + * Mean value on U axis + * \param v_min + * Minimum value on V axis + * \param v_max + * Maximum value on V axis + * \param v_mean + * Mean value on V axis + * \param range + * Scale factor + * \param type + * Signature type + * + * \return A vision_signature_s_t that can be set using vision_set_signature + */ +vision_signature_s_t vision_signature_from_utility(const int32_t id, const int32_t u_min, const int32_t u_max, + const int32_t u_mean, const int32_t v_min, const int32_t v_max, + const int32_t v_mean, const float range, const int32_t type); + +/** + * Creates a color code that represents a combination of the given signature + * IDs. If fewer than 5 signatures are to be a part of the color code, pass 0 + * for the additional function parameters. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - Fewer than two signatures have been provided, or one of the + * signatures is out of its [1-7] range. + * + * \param port + * The V5 port number from 1-21 + * \param sig_id1 + * The first signature id [1-7] to add to the color code + * \param sig_id2 + * The second signature id [1-7] to add to the color code + * \param sig_id3 + * The third signature id [1-7] to add to the color code + * \param sig_id4 + * The fourth signature id [1-7] to add to the color code + * \param sig_id5 + * The fifth signature id [1-7] to add to the color code + * + * \return A vision_color_code_t object containing the color code information. + */ +vision_color_code_t vision_create_color_code(uint8_t port, const uint32_t sig_id1, const uint32_t sig_id2, + const uint32_t sig_id3, const uint32_t sig_id4, const uint32_t sig_id5); + +/** + * Gets the nth largest object according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * EHOSTDOWN - Reading the vision sensor failed for an unknown reason. + * + * \param port + * The V5 port number from 1-21 + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * + * \return The vision_object_s_t object corresponding to the given size id, or + * PROS_ERR if an error occurred. + */ +vision_object_s_t vision_get_by_size(uint8_t port, const uint32_t size_id); + +/** + * Gets the nth largest object of the given signature according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * EHOSTDOWN - Reading the vision sensor failed for an unknown reason. + * + * \param port + * The V5 port number from 1-21 + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param signature + * The signature ID [1-7] for which an object will be returned. + * + * \return The vision_object_s_t object corresponding to the given signature and + * size_id, or PROS_ERR if an error occurred. + */ +vision_object_s_t vision_get_by_sig(uint8_t port, const uint32_t size_id, const uint32_t sig_id); + +/** + * Gets the nth largest object of the given color code according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * EAGAIN - Reading the Vision Sensor failed for an unknown reason. + * + * \param port + * The V5 port number from 1-21 + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param color_code + * The vision_color_code_t for which an object will be returned + * + * \return The vision_object_s_t object corresponding to the given color code + * and size_id, or PROS_ERR if an error occurred. + */ +vision_object_s_t vision_get_by_code(uint8_t port, const uint32_t size_id, const vision_color_code_t color_code); + +/** + * Gets the exposure parameter of the Vision Sensor. See + * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting + * for more detials. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The current exposure setting from [0,150], PROS_ERR if an error + * occurred + */ +int32_t vision_get_exposure(uint8_t port); + +/** + * Gets the number of objects currently detected by the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The number of objects detected on the specified vision sensor. + * Returns PROS_ERR if the port was invalid or an error occurred. + */ +int32_t vision_get_object_count(uint8_t port); + +/** + * Get the white balance parameter of the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \return The current RGB white balance setting of the sensor + */ +int32_t vision_get_white_balance(uint8_t port); + +/** + * Prints the contents of the signature as an initializer list to the terminal. + * + * \param sig + * The signature for which the contents will be printed + * + * \return 1 if no errors occured, PROS_ERR otherwise + */ +int32_t vision_print_signature(const vision_signature_s_t sig); + +/** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21), or + * fewer than object_count number of objects were found. + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * + * \param port + * The V5 port number from 1-21 + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param object_count + * The number of objects to read + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ +int32_t vision_read_by_size(uint8_t port, const uint32_t size_id, const uint32_t object_count, + vision_object_s_t* const object_arr); + +/** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21), or + * fewer than object_count number of objects were found. + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * + * \param port + * The V5 port number from 1-21 + * \param object_count + * The number of objects to read + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param signature + * The signature ID [1-7] for which objects will be returned. + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ +int32_t vision_read_by_sig(uint8_t port, const uint32_t size_id, const uint32_t sig_id, const uint32_t object_count, + vision_object_s_t* const object_arr); + +/** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21), or + * fewer than object_count number of objects were found. + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param object_count + * The number of objects to read + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param color_code + * The vision_color_code_t for which objects will be returned + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ +int32_t vision_read_by_code(uint8_t port, const uint32_t size_id, const vision_color_code_t color_code, + const uint32_t object_count, vision_object_s_t* const object_arr); + +/** + * Gets the object detection signature with the given id number. + * + * \param port + * The V5 port number from 1-21 + * \param signature_id + * The signature id to read + * + * \return A vision_signature_s_t containing information about the signature. + */ +vision_signature_s_t vision_get_signature(uint8_t port, const uint8_t signature_id); + +/** + * Stores the supplied object detection signature onto the vision sensor. + * + * NOTE: This saves the signature in volatile memory, and the signature will be + * lost as soon as the sensor is powered down. + * + * \param port + * The V5 port number from 1-21 + * \param signature_id + * The signature id to store into + * \param[in] signature_ptr + * A pointer to the signature to save + * + * \return 1 if no errors occured, PROS_ERR otherwise + */ +int32_t vision_set_signature(uint8_t port, const uint8_t signature_id, vision_signature_s_t* const signature_ptr); + +/** + * Enables/disables auto white-balancing on the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param enabled + * Pass 0 to disable, 1 to enable + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_auto_white_balance(uint8_t port, const uint8_t enable); + +/** + * Sets the exposure parameter of the Vision Sensor. See + * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting + * for more detials. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param percent + * The new exposure setting from [0,150] + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_exposure(uint8_t port, const uint8_t exposure); + +/** + * Sets the vision sensor LED color, overriding the automatic behavior. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param rgb + * An RGB code to set the LED to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_led(uint8_t port, const int32_t rgb); + +/** + * Sets the white balance parameter of the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param rgb + * The new RGB white balance setting of the sensor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_white_balance(uint8_t port, const int32_t rgb); + +/** + * Sets the (0,0) coordinate for the Field of View. + * + * This will affect the coordinates returned for each request for a + * vision_object_s_t from the sensor, so it is recommended that this function + * only be used to configure the sensor at the beginning of its use. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * \param zero_point + * One of vision_zero_e_t to set the (0,0) coordinate for the FOV + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_zero_point(uint8_t port, vision_zero_e_t zero_point); + +/** + * Sets the Wi-Fi mode of the Vision sensor + * + * This functions uses the following values of errno when an error state is + * reached: + * EINVAL - The given port is not within the range of V5 ports (1-21) + * EACCESS - Anothe resources is currently trying to access the port + * + * \param port + * The V5 port number from 1-21 + * \param enable + * Disable Wi-Fi on the Vision sensor if 0, enable otherwise (e.g. 1) + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t vision_set_wifi_mode(uint8_t port, const uint8_t enable); + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif + +#endif // _PROS_VISION_H_ diff --git a/include/pros/vision.hpp b/include/pros/vision.hpp new file mode 100644 index 0000000..496508a --- /dev/null +++ b/include/pros/vision.hpp @@ -0,0 +1,421 @@ +/** + * \file pros/vision.hpp + * + * Contains prototypes for the VEX Vision Sensor-related functions in C++. + * + * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html to learn + * more. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * Copyright (c) 2017-2018, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef _PROS_VISION_HPP_ +#define _PROS_VISION_HPP_ + +#include "pros/vision.h" + +#include + +namespace pros { +class Vision { + public: + /** + * Create a Vision Sensor object on the given port. + * + * \param port + * The V5 port number from 1-21 + * \param zero_point + * One of vision_zero_e_t to set the (0,0) coordinate for the FOV + */ + Vision(std::uint8_t port, vision_zero_e_t zero_point = E_VISION_ZERO_TOPLEFT); + + /** + * Clears the vision sensor LED color, reseting it back to its default + * behavior, displaying the most prominent object signature color. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t clear_led(void) const; + + /** + * Creates a signature from the vision sensor utility + * + * \param id + * The signature ID + * \param u_min + * Minimum value on U axis + * \param u_max + * Maximum value on U axis + * \param u_mean + * Mean value on U axis + * \param v_min + * Minimum value on V axis + * \param v_max + * Maximum value on V axis + * \param v_mean + * Mean value on V axis + * \param rgb + * Scale factor + * \param type + * Signature type + * + * \return A vision_signature_s_t that can be set using Vision::set_signature + */ + static vision_signature_s_t signature_from_utility(const std::int32_t id, const std::int32_t u_min, + const std::int32_t u_max, const std::int32_t u_mean, + const std::int32_t v_min, const std::int32_t v_max, + const std::int32_t v_mean, const float range, + const std::int32_t type); + + /** + * Creates a color code that represents a combination of the given signature + * IDs. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - Fewer than two signatures have been provided, or one of the + * signatures is out of its [1-7] range. + * + * \param sig_id1 + * The first signature id [1-7] to add to the color code + * \param sig_id2 + * The second signature id [1-7] to add to the color code + * \param sig_id3 + * The third signature id [1-7] to add to the color code + * \param sig_id4 + * The fourth signature id [1-7] to add to the color code + * \param sig_id5 + * The fifth signature id [1-7] to add to the color code + * + * \return A vision_color_code_t object containing the color code information. + */ + vision_color_code_t create_color_code(const std::uint32_t sig_id1, const std::uint32_t sig_id2, + const std::uint32_t sig_id3 = 0, const std::uint32_t sig_id4 = 0, + const std::uint32_t sig_id5 = 0) const; + + /** + * Gets the nth largest object according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * EHOSTDOWN - Reading the vision sensor failed for an unknown reason. + * + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * + * \return The vision_object_s_t object corresponding to the given size id, or + * PROS_ERR if an error occurred. + */ + vision_object_s_t get_by_size(const std::uint32_t size_id) const; + + /** + * Gets the nth largest object of the given signature according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * EHOSTDOWN - Reading the vision sensor failed for an unknown reason. + * + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param signature + * The vision_signature_s_t signature for which an object will be + * returned. + * + * \return The vision_object_s_t object corresponding to the given signature + * and size_id, or PROS_ERR if an error occurred. + */ + vision_object_s_t get_by_sig(const std::uint32_t size_id, const std::uint32_t sig_id) const; + + /** + * Gets the nth largest object of the given color code according to size_id. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * EAGAIN - Reading the Vision Sensor failed for an unknown reason. + * + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param color_code + * The vision_color_code_t for which an object will be returned + * + * \return The vision_object_s_t object corresponding to the given color code + * and size_id, or PROS_ERR if an error occurred. + */ + vision_object_s_t get_by_code(const std::uint32_t size_id, const vision_color_code_t color_code) const; + + /** + * Gets the exposure parameter of the Vision Sensor. See + * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting + * for more detials. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The current exposure parameter from [0,150], + * PROS_ERR if an error occurred + */ + std::int32_t get_exposure(void) const; + + /** + * Gets the number of objects currently detected by the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The number of objects detected on the specified vision sensor. + * Returns PROS_ERR if the port was invalid or an error occurred. + */ + std::int32_t get_object_count(void) const; + + /** + * Gets the object detection signature with the given id number. + * + * \param signature_id + * The signature id to read + * + * \return A vision_signature_s_t containing information about the signature. + */ + vision_signature_s_t get_signature(const std::uint8_t signature_id) const; + + /** + * Get the white balance parameter of the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \return The current RGB white balance setting of the sensor + */ + std::int32_t get_white_balance(void) const; + + /** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param object_count + * The number of objects to read + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ + std::int32_t read_by_size(const std::uint32_t size_id, const std::uint32_t object_count, + vision_object_s_t* const object_arr) const; + + /** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * EDOM - size_id is greater than the number of available objects. + * EHOSTDOWN - Reading the vision sensor failed for an unknown reason. + * + * \param object_count + * The number of objects to read + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param signature + * The vision_signature_s_t signature for which an object will be + * returned. + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ + std::int32_t read_by_sig(const std::uint32_t size_id, const std::uint32_t sig_id, const std::uint32_t object_count, + vision_object_s_t* const object_arr) const; + + /** + * Reads up to object_count object descriptors into object_arr. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - Fewer than object_count number of objects were found. + * EACCES - Another resource is currently trying to access the port. + * + * \param object_count + * The number of objects to read + * \param size_id + * The object to read from a list roughly ordered by object size + * (0 is the largest item, 1 is the second largest, etc.) + * \param color_code + * The vision_color_code_t for which objects will be returned + * \param[out] object_arr + * A pointer to copy the objects into + * + * \return The number of object signatures copied. This number will be less than + * object_count if there are fewer objects detected by the vision sensor. + * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects + * than size_id were found. All objects in object_arr that were not found are + * given VISION_OBJECT_ERR_SIG as their signature. + */ + int32_t read_by_code(const std::uint32_t size_id, const vision_color_code_t color_code, + const std::uint32_t object_count, vision_object_s_t* const object_arr) const; + + /** + * Prints the contents of the signature as an initializer list to the terminal. + * + * \param sig + * The signature for which the contents will be printed + * + * \return 1 if no errors occured, PROS_ERR otherwise + */ + static std::int32_t print_signature(const vision_signature_s_t sig); + + /** + * Enables/disables auto white-balancing on the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param enabled + * Pass 0 to disable, 1 to enable + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_auto_white_balance(const std::uint8_t enable) const; + + /** + * Sets the exposure parameter of the Vision Sensor. See + * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting + * for more detials. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param percent + * The new exposure setting from [0,150]. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_exposure(const std::uint8_t exposure) const; + + /** + * Sets the vision sensor LED color, overriding the automatic behavior. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param rgb + * An RGB code to set the LED to + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_led(const std::int32_t rgb) const; + + /** + * Stores the supplied object detection signature onto the vision sensor. + * + * NOTE: This saves the signature in volatile memory, and the signature will be + * lost as soon as the sensor is powered down. + * + * \param signature_id + * The signature id to store into + * \param[in] signature_ptr + * A pointer to the signature to save + * + * \return 1 if no errors occured, PROS_ERR otherwise + */ + std::int32_t set_signature(const std::uint8_t signature_id, vision_signature_s_t* const signature_ptr) const; + + /** + * Sets the white balance parameter of the Vision Sensor. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param rgb + * The new RGB white balance setting of the sensor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_white_balance(const std::int32_t rgb) const; + + /** + * Sets the (0,0) coordinate for the Field of View. + * + * This will affect the coordinates returned for each request for a + * vision_object_s_t from the sensor, so it is recommended that this function + * only be used to configure the sensor at the beginning of its use. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the port. + * + * \param zero_point + * One of vision_zero_e_t to set the (0,0) coordinate for the FOV + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_zero_point(vision_zero_e_t zero_point) const; + + /** + * Sets the Wi-Fi mode of the Vision sensor + * + * This functions uses the following values of errno when an error state is + * reached: + * EINVAL - The given port is not within the range of V5 ports (1-21) + * EACCESS - Anothe resources is currently trying to access the port + * + * \param enable + * Disable Wi-Fi on the Vision sensor if 0, enable otherwise (e.g. 1) + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + std::int32_t set_wifi_mode(const std::uint8_t enable) const; + + private: + std::uint8_t _port; +}; +} // namespace pros +#endif // _PROS_VISION_HPP_ diff --git a/project.pros b/project.pros new file mode 100644 index 0000000..03a3ec6 --- /dev/null +++ b/project.pros @@ -0,0 +1,253 @@ +{ + "py/object": "pros.conductor.project.Project", + "py/state": { + "project_name": "Empty Pros Project", + "target": "v5", + "templates": { + "kernel": { + "location": "C:\\Users\\lerker100\\AppData\\Roaming\\PROS\\templates\\kernel@3.1.6", + "metadata": { + "cold_addr": "58720256", + "cold_output": "bin/cold.package.bin", + "hot_addr": "125829120", + "hot_output": "bin/hot.package.bin", + "origin": "pros-mainline", + "output": "bin/monolith.bin" + }, + "name": "kernel", + "py/object": "pros.conductor.templates.local_template.LocalTemplate", + "supported_kernels": null, + "system_files": [ + "include/display/lv_core/lv_style.h", + "include/pros/vision.hpp", + "include/display/lv_objx/lv_ta.h", + "include/pros/motors.hpp", + "common.mk", + "include/pros/adi.h", + "include/pros/colors.h", + "include/display/lv_misc/lv_mem.h", + "include/display/lv_misc/lv_font.h", + "include/display/lv_objx/lv_kb.h", + "include/display/lv_hal/lv_hal_disp.h", + "include/display/lv_core/lv_core.mk", + "include/display/lv_misc/lv_circ.h", + "include/display/lv_objx/lv_objx.mk", + "include/display/lv_objx/lv_lmeter.h", + "include/display/lv_misc/lv_templ.h", + "include/display/lv_misc/lv_math.h", + "include/display/lv_draw/lv_draw.mk", + "include/display/lv_objx/lv_label.h", + "include/display/lv_conf.h", + "include/display/lv_draw/lv_draw_vbasic.h", + "include/pros/adi.hpp", + "include/display/lv_core/lv_obj.h", + "include/display/lv_themes/lv_theme.h", + "include/display/lv_objx/lv_chart.h", + "include/display/lv_objx/lv_led.h", + "include/display/lv_objx/lv_ddlist.h", + "include/display/lv_misc/lv_task.h", + "include/display/lv_themes/lv_theme_templ.h", + "include/pros/motors.h", + "include/display/lv_themes/lv_theme_alien.h", + "include/display/lv_misc/lv_anim.h", + "include/display/lv_misc/lv_ufs.h", + "include/display/lv_core/lv_refr.h", + "include/display/lv_objx/lv_page.h", + "include/pros/misc.hpp", + "include/display/lv_objx/lv_sw.h", + "include/display/lv_misc/lv_txt.h", + "include/display/lv_hal/lv_hal_indev.h", + "include/pros/apix.h", + "include/display/lv_core/lv_vdb.h", + "include/display/lv_hal/lv_hal.h", + "include/display/lv_objx/lv_cb.h", + "include/display/lv_misc/lv_fonts/lv_symbol_def.h", + "include/display/lv_objx/lv_gauge.h", + "include/display/lv_misc/lv_trigo.h", + "include/pros/api_legacy.h", + "firmware/v5-hot.ld", + "include/display/lv_core/lv_indev.h", + "include/display/lv_objx/lv_bar.h", + "include/pros/rtos.hpp", + "include/display/lv_misc/lv_fs.h", + "firmware/v5.ld", + "include/display/lv_hal/lv_hal_tick.h", + "include/display/lv_objx/lv_roller.h", + "include/display/lv_themes/lv_themes.mk", + "include/display/lv_misc/lv_area.h", + "include/display/lv_core/lv_group.h", + "include/display/lv_draw/lv_draw.h", + "include/display/lv_objx/lv_objx_templ.h", + "include/display/lv_objx/lv_btn.h", + "include/display/lv_objx/lv_btnm.h", + "include/display/lv_objx/lv_mbox.h", + "include/display/lv_objx/lv_line.h", + "include/api.h", + "include/display/lv_objx/lv_list.h", + "include/pros/llemu.h", + "include/display/lv_objx/lv_tabview.h", + "include/display/lv_draw/lv_draw_rbasic.h", + "include/display/lvgl.h", + "include/display/lv_hal/lv_hal.mk", + "include/pros/rtos.h", + "include/pros/misc.h", + "include/display/lv_misc/lv_ll.h", + "include/display/README.md", + "include/display/lv_misc/lv_misc.mk", + "include/display/lv_objx/lv_img.h", + "include/display/lv_objx/lv_cont.h", + "include/display/lv_misc/lv_fonts/lv_fonts.mk", + "include/display/lv_misc/lv_color.h", + "include/display/lv_objx/lv_win.h", + "include/display/licence.txt", + "include/pros/llemu.hpp", + "firmware/v5-common.ld", + "firmware/libpros.a", + "include/display/lv_objx/lv_slider.h", + "include/pros/vision.h" + ], + "target": "v5", + "user_files": [ + "src/autonomous.cpp", + "src/opcontrol.c", + "src/opcontrol.cc", + "src/initialize.cpp", + "src/autonomous.c", + "src/autonomous.cc", + "src/initialize.cc", + "include/main.hh", + "Makefile", + "src/initialize.c", + "src/opcontrol.cpp", + "include/main.h", + "include/main.hpp" + ], + "version": "3.1.6" + }, + "okapilib": { + "location": "C:\\Users\\lerker100\\AppData\\Roaming\\PROS\\templates\\okapilib@3.3.12", + "metadata": { + "origin": "pros-mainline" + }, + "name": "okapilib", + "py/object": "pros.conductor.templates.local_template.LocalTemplate", + "supported_kernels": "^3.1.6", + "system_files": [ + "include/okapi/impl/device/controllerUtil.hpp", + "include/okapi/api/units/QArea.hpp", + "include/okapi/api/control/controllerInput.hpp", + "include/okapi/api/coreProsAPI.hpp", + "include/okapi/api/device/motor/abstractMotor.hpp", + "include/okapi/api/control/async/asyncPositionController.hpp", + "include/okapi/impl/device/button/controllerButton.hpp", + "include/okapi/api/filter/filter.hpp", + "include/okapi/api/filter/composableFilter.hpp", + "firmware/okapilib.a", + "include/okapi/api/units/QMass.hpp", + "include/okapi/api/units/QVolume.hpp", + "include/okapi/impl/device/rotarysensor/potentiometer.hpp", + "include/okapi/impl/util/timeUtilFactory.hpp", + "include/okapi/impl/device/rotarysensor/integratedEncoder.hpp", + "include/okapi/api/chassis/model/xDriveModel.hpp", + "include/okapi/api/filter/medianFilter.hpp", + "include/okapi/impl/control/iterative/iterativeControllerFactory.hpp", + "include/okapi/impl/device/vision.hpp", + "include/okapi/api/filter/demaFilter.hpp", + "include/okapi/api/util/mathUtil.hpp", + "include/okapi/api/chassis/model/chassisModel.hpp", + "include/okapi/api/util/logging.hpp", + "include/okapi/pathfinder/include/pathfinder/trajectory.h", + "include/okapi/api/util/abstractRate.hpp", + "include/okapi/api/control/iterative/iterativeController.hpp", + "include/okapi/api/control/async/asyncPosPidController.hpp", + "include/okapi/impl/filter/velMathFactory.hpp", + "include/okapi/pathfinder/include/pathfinder/spline.h", + "include/okapi/api/filter/passthroughFilter.hpp", + "include/okapi/api/units/QSpeed.hpp", + "include/okapi/api/control/async/asyncPosIntegratedController.hpp", + "include/okapi/pathfinder/include/pathfinder/io.h", + "include/okapi/impl/device/controller.hpp", + "include/okapi/api/filter/emaFilter.hpp", + "include/okapi/impl/device/adiUltrasonic.hpp", + "include/okapi/api/chassis/controller/chassisController.hpp", + "include/okapi/pathfinder/include/pathfinder/modifiers/swerve.h", + "include/okapi/api/control/util/flywheelSimulator.hpp", + "include/okapi/api/control/async/asyncLinearMotionProfileController.hpp", + "include/okapi/api/control/iterative/iterativePosPidController.hpp", + "include/okapi/api/filter/velMath.hpp", + "include/okapi/api/units/QAngle.hpp", + "include/okapi/impl/util/timer.hpp", + "include/okapi/impl/device/motor/motor.hpp", + "include/okapi/api/control/async/asyncController.hpp", + "include/okapi/impl/util/rate.hpp", + "include/okapi/api/control/iterative/iterativeVelocityController.hpp", + "include/okapi/api.hpp", + "include/okapi/api/units/QTime.hpp", + "include/okapi/api/units/QAngularSpeed.hpp", + "include/okapi/api/control/async/asyncVelPidController.hpp", + "include/okapi/api/control/async/asyncVelocityController.hpp", + "include/okapi/api/units/QAngularAcceleration.hpp", + "include/okapi/api/units/RQuantity.hpp", + "include/okapi/api/filter/ekfFilter.hpp", + "include/okapi/api/control/util/pidTuner.hpp", + "include/okapi/api/control/async/asyncMotionProfileController.hpp", + "include/okapi/api/device/rotarysensor/continuousRotarySensor.hpp", + "include/okapi/api/units/QFrequency.hpp", + "include/okapi/api/util/timeUtil.hpp", + "include/okapi/impl/device/motor/adiMotor.hpp", + "include/okapi/api/chassis/model/readOnlyChassisModel.hpp", + "include/okapi/api/chassis/controller/chassisScales.hpp", + "include/okapi/api/chassis/controller/chassisControllerPid.hpp", + "include/okapi/impl/control/util/pidTunerFactory.hpp", + "include/okapi/api/control/controllerOutput.hpp", + "include/okapi/api/chassis/controller/chassisControllerIntegrated.hpp", + "include/okapi/impl/control/async/asyncControllerFactory.hpp", + "include/okapi/pathfinder/include/pathfinder/fit.h", + "include/okapi/api/filter/averageFilter.hpp", + "include/okapi/api/chassis/model/threeEncoderSkidSteerModel.hpp", + "include/okapi/api/filter/filteredControllerInput.hpp", + "include/okapi/api/util/supplier.hpp", + "include/okapi/impl/chassis/controller/chassisControllerFactory.hpp", + "include/okapi/pathfinder/include/pathfinder/followers/distance.h", + "include/okapi/impl/control/util/controllerRunnerFactory.hpp", + "include/okapi/impl/control/util/settledUtilFactory.hpp", + "include/okapi/api/units/QPressure.hpp", + "include/okapi/pathfinder/include/pathfinder/modifiers/tank.h", + "include/okapi/api/control/iterative/iterativeMotorVelocityController.hpp", + "include/okapi/api/device/button/buttonBase.hpp", + "include/okapi/api/control/async/asyncVelIntegratedController.hpp", + "include/okapi/impl/device/button/adiButton.hpp", + "include/okapi/pathfinder/include/pathfinder/mathutil.h", + "include/okapi/api/units/QForce.hpp", + "include/okapi/api/chassis/model/skidSteerModel.hpp", + "include/okapi/api/control/iterative/iterativeVelPidController.hpp", + "include/okapi/impl/device/rotarysensor/adiGyro.hpp", + "include/okapi/api/units/QJerk.hpp", + "include/okapi/api/control/async/asyncWrapper.hpp", + "include/okapi/api/units/QTorque.hpp", + "include/okapi/api/units/QAcceleration.hpp", + "include/okapi/api/util/abstractTimer.hpp", + "include/okapi/api/control/util/controllerRunner.hpp", + "include/okapi/api/device/rotarysensor/rotarySensor.hpp", + "include/okapi/api/control/util/settledUtil.hpp", + "include/okapi/impl/device/motor/motorGroup.hpp", + "include/okapi/impl/device/rotarysensor/adiEncoder.hpp", + "include/okapi/pathfinder/include/pathfinder.h", + "include/okapi/api/device/button/abstractButton.hpp", + "include/okapi/api/units/QAngularJerk.hpp", + "include/okapi/pathfinder/include/pathfinder/structs.h", + "include/okapi/pathfinder/include/pathfinder/followers/encoder.h", + "include/okapi/impl/chassis/model/chassisModelFactory.hpp", + "include/okapi/pathfinder/include/pathfinder/lib.h", + "include/okapi/api/control/closedLoopController.hpp", + "include/okapi/api/units/QLength.hpp", + "include/okapi/api/control/iterative/iterativePositionController.hpp" + ], + "target": "v5", + "user_files": [], + "version": "3.3.12" + } + }, + "upload_options": {} + } +} \ No newline at end of file diff --git a/src/autonomous.cpp b/src/autonomous.cpp new file mode 100644 index 0000000..db70252 --- /dev/null +++ b/src/autonomous.cpp @@ -0,0 +1,14 @@ +#include "main.h" + +/** + * Runs the user autonomous code. This function will be started in its own task + * with the default priority and stack size whenever the robot is enabled via + * the Field Management System or the VEX Competition Switch in the autonomous + * mode. Alternatively, this function may be called in initialize or opcontrol + * for non-competition testing purposes. + * + * If the robot is disabled or communications is lost, the autonomous task + * will be stopped. Re-enabling the robot will restart the task, not re-start it + * from where it left off. + */ +void autonomous() {} diff --git a/src/initialize.cpp b/src/initialize.cpp new file mode 100644 index 0000000..77b7fe4 --- /dev/null +++ b/src/initialize.cpp @@ -0,0 +1,42 @@ +#include "main.h" + +void on_center_button() { + static bool pressed = false; + pressed = !pressed; + if (pressed) { + pros::lcd::set_text(2, "I was pressed!"); + } else { + pros::lcd::clear_line(2); + } +} + +/** + * Runs initialization code. This occurs as soon as the program is started. + * + * All other competition modes are blocked by initialize; it is recommended + * to keep execution time for this mode under a few seconds. + */ +void initialize() { + pros::lcd::initialize(); + pros::lcd::set_text(1, "Hello PROS User!"); + + pros::lcd::register_btn1_cb(on_center_button); +} + +/** + * Runs while the robot is in the disabled state of Field Management System or + * the VEX Competition Switch, following either autonomous or opcontrol. When + * the robot is enabled, this task will exit. + */ +void disabled() {} + +/** + * Runs after initialize(), and before autonomous when connected to the Field + * Management System or the VEX Competition Switch. This is intended for + * competition-specific initialization routines, such as an autonomous selector + * on the LCD. + * + * This task will exit when the robot is enabled and autonomous or opcontrol + * starts. + */ +void competition_initialize() {} diff --git a/src/opcontrol.cpp b/src/opcontrol.cpp new file mode 100644 index 0000000..7b7d123 --- /dev/null +++ b/src/opcontrol.cpp @@ -0,0 +1,31 @@ +#include "main.h" + +/** + * Runs the operator control code. This function will be started in its own task + * with the default priority and stack size whenever the robot is enabled via + * the Field Management System or the VEX Competition Switch in the operator + * control mode. + * + * If no competition control is connected, this function will run immediately + * following initialize(). + * + * If the robot is disabled or communications is lost, the + * operator control task will be stopped. Re-enabling the robot will restart the + * task, not resume it from where it left off. + */ +void opcontrol() { + pros::Controller master(pros::E_CONTROLLER_MASTER); + pros::Motor left_mtr(1); + pros::Motor right_mtr(2); + while (true) { + pros::lcd::print(0, "%d %d %d", (pros::lcd::read_buttons() & LCD_BTN_LEFT) >> 2, + (pros::lcd::read_buttons() & LCD_BTN_CENTER) >> 1, + (pros::lcd::read_buttons() & LCD_BTN_RIGHT) >> 0); + int left = master.get_analog(ANALOG_LEFT_Y); + int right = master.get_analog(ANALOG_RIGHT_Y); + + left_mtr = left; + right_mtr = right; + pros::delay(20); + } +}