diff --git a/Makefile b/Makefile index 30e721747..45d8554ce 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,9 @@ all_clean: @$(ECHO) " CLEAN $(call toprel, $(BUILD_DIR))" $(V1) [ ! -d "$(BUILD_DIR)" ] || $(RM) -rf "$(BUILD_DIR)" +.PONY: clean +clean: all_clean + $(DL_DIR): $(MKDIR) -p $@ @@ -144,6 +147,12 @@ $(TOOLS_DIR): $(BUILD_DIR): $(MKDIR) -p $@ +$(PACKAGE_DIR): + $(MKDIR) -p $@ + +$(DIST_DIR): + $(MKDIR) -p $@ + ############################## # # UAVObjects @@ -243,8 +252,8 @@ EF_TARGETS := $(addprefix ef_, $(EF_BOARDS)) # When building any of the "all_*" targets, tell all sub makefiles to display # additional details on each line of output to describe which build and target # that each line applies to. The same applies also to all, opfw_resource, -# package and clean_package targets -ifneq ($(strip $(filter all_% all opfw_resource package clean_package,$(MAKECMDGOALS))),) +# package targets +ifneq ($(strip $(filter all_% all opfw_resource package,$(MAKECMDGOALS))),) export ENABLE_MSG_EXTRA := yes endif @@ -766,51 +775,29 @@ $(OPFW_RESOURCE): $(FW_TARGETS) $(V1) $(ECHO) $(QUOTE)$(OPFW_CONTENTS)$(QUOTE) > $@ # If opfw_resource or all firmware are requested, GCS should depend on the resource -ifneq ($(strip $(filter opfw_resource all all_fw all_flight,$(MAKECMDGOALS))),) +ifneq ($(strip $(filter opfw_resource all all_fw all_flight package,$(MAKECMDGOALS))),) $(eval openpilotgcs_qmake: $(OPFW_RESOURCE)) endif -# Packaging targets: package, clean_package -# - removes build directory (clean_package only) +# Packaging targets: package # - builds all firmware, opfw_resource, gcs # - copies firmware into a package directory # - calls paltform-specific packaging script -# Do some checks and define some values if package is requested -ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),) - # Define some variables - export PACKAGE_LBL := $(shell $(VERSION_INFO) --format=\$${LABEL}) - export PACKAGE_NAME := OpenPilot - export PACKAGE_SEP := - - - # We can only package release builds - ifneq ($(GCS_BUILD_CONF),release) - $(error Packaging is currently supported for release builds only) - endif - - # Packaged GCS should depend on opfw_resource - ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),) - $(eval openpilotgcs_qmake: $(OPFW_RESOURCE)) - endif - - # Clean the build directory if clean_package is requested - ifneq ($(strip $(filter clean_package,$(MAKECMDGOALS))),) - $(info Cleaning build directory before packaging...) - ifneq ($(shell $(MAKE) all_clean >/dev/null 2>&1 && $(ECHO) "clean"), clean) - $(error Cannot clean build directory) - endif - - .PHONY: clean_package - clean_package: package - endif -endif +# Define some variables +export PACKAGE_LBL := $(shell $(VERSION_INFO) --format=\$${LABEL}) +export PACKAGE_NAME := OpenPilot +export PACKAGE_SEP := - .PHONY: package -package: all_fw all_ground uavobjects_matlab - @$(ECHO) "Packaging for $(UNAME) $(ARCH) into $(call toprel, $(PACKAGE_DIR)) directory" - $(V1) [ ! -d "$(PACKAGE_DIR)" ] || $(RM) -rf "$(PACKAGE_DIR)" - $(V1) $(MKDIR) -p "$(PACKAGE_DIR)" - $(MAKE) --no-print-directory -C $(ROOT_DIR)/package --file=$(UNAME).mk $@ + +include $(ROOT_DIR)/package/$(UNAME).mk + +package: all_fw all_ground uavobjects_matlab $(PACKAGE_DIR) +ifneq ($(GCS_BUILD_CONF),release) + # We can only package release builds + $(error Packaging is currently supported for release builds only) +endif ############################## # @@ -893,60 +880,23 @@ build-info: # ############################## +DIST_VER_INFO := $(DIST_DIR)/version-info.json + +.PHONY: $(DIST_VER_INFO) # Because to many deps to list +$(DIST_VER_INFO): $(DIST_DIR) + $(V1) $(VERSION_INFO) --jsonpath="$(DIST_DIR)" + .PHONY: dist -dist: +dist: $(DIST_DIR) $(DIST_VER_INFO) @$(ECHO) " SOURCE FOR DISTRIBUTION $(call toprel, $(DIST_DIR))" - $(V1) $(MKDIR) -p "$(DIST_DIR)" - $(V1) $(VERSION_INFO) \ - --jsonpath="$(DIST_DIR)" $(eval DIST_NAME := $(call toprel, "$(DIST_DIR)/OpenPilot-$(shell git describe).tar")) $(V1) git archive --prefix="OpenPilot/" -o "$(DIST_NAME)" HEAD $(V1) tar --append --file="$(DIST_NAME)" \ --transform='s,.*version-info.json,OpenPilot/version-info.json,' \ - $(call toprel, "$(DIST_DIR)/version-info.json") + $(call toprel, "$(DIST_VER_INFO)") $(V1) gzip -f "$(DIST_NAME)" - -############################## -# -# Install OpenPilot -# -############################## -prefix := /usr/local -bindir := $(prefix)/bin -libdir := $(prefix)/lib -datadir := $(prefix)/share - -INSTALL = cp -a --no-preserve=ownership -LN = ln -LN_S = ln -s - -ifeq ($(MAKECMDGOALS), install) - ifneq ($(UNAME), Linux) - $(error install only supported for Linux) - endif -endif - - -.PHONY: install -install: - @$(ECHO) " INSTALLING GCS TO $(DESTDIR)/)" - $(V1) $(MKDIR) -p $(DESTDIR)$(bindir) - $(V1) $(MKDIR) -p $(DESTDIR)$(libdir) - $(V1) $(MKDIR) -p $(DESTDIR)$(datadir) - $(V1) $(MKDIR) -p $(DESTDIR)$(datadir)/applications - $(V1) $(MKDIR) -p $(DESTDIR)$(datadir)/pixmaps - $(V1) $(MKDIR) -p $(DESTDIR)$(udevdir) - $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/bin/openpilotgcs $(DESTDIR)$(bindir) - $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/bin/udp_test $(DESTDIR)$(bindir) - $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/lib/openpilotgcs $(DESTDIR)$(libdir) - $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/share/openpilotgcs $(DESTDIR)$(datadir) - $(V1) $(INSTALL) $(ROOT_DIR)/package/linux/openpilot.desktop $(DESTDIR)$(datadir)/applications - $(V1) $(INSTALL) $(ROOT_DIR)/package/linux/openpilot.png $(DESTDIR)$(datadir)/pixmaps - $(V1) rm $(DESTDIR)/$(datadir)/openpilotgcs/translations/Makefile - - ############################## # # Help message, the default Makefile goal @@ -1079,7 +1029,6 @@ help: @$(ECHO) " Supported groups are ($(UAVOBJ_TARGETS))" @$(ECHO) @$(ECHO) " [Packaging]" - @$(ECHO) " clean_package - Clean, build and package the OpenPilot platform-dependent package" @$(ECHO) " package - Build and package the OpenPilot platform-dependent package (no clean)" @$(ECHO) " opfw_resource - Generate resources to embed firmware binaries into the GCS" @$(ECHO) " dist - Generate source archive for distribution" diff --git a/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.3DS b/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.3DS new file mode 100755 index 000000000..1217e54de Binary files /dev/null and b/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.3DS differ diff --git a/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.jpg b/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.jpg new file mode 100755 index 000000000..de2db9dcb Binary files /dev/null and b/artwork/3D Model/multi/blackout/BlackoutMiniHQuad.jpg differ diff --git a/artwork/3D Model/multi/blackout/TEXTURE.PNG b/artwork/3D Model/multi/blackout/TEXTURE.PNG new file mode 100755 index 000000000..3c430b5df Binary files /dev/null and b/artwork/3D Model/multi/blackout/TEXTURE.PNG differ diff --git a/flight/libraries/inc/sanitycheck.h b/flight/libraries/inc/sanitycheck.h index 4c6d8e990..1c270f8e6 100644 --- a/flight/libraries/inc/sanitycheck.h +++ b/flight/libraries/inc/sanitycheck.h @@ -32,6 +32,9 @@ #include +#include +#include + typedef enum { FRAME_TYPE_MULTIROTOR, FRAME_TYPE_HELI, @@ -40,6 +43,8 @@ typedef enum { FRAME_TYPE_CUSTOM, } FrameType_t; +typedef SystemAlarmsExtendedAlarmStatusOptions (SANITYCHECK_CustomHook_function)(); + #define SANITYCHECK_STATUS_ERROR_NONE SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE #define SANITYCHECK_STATUS_ERROR_FLIGHTMODE SYSTEMALARMS_EXTENDEDALARMSTATUS_FLIGHTMODE @@ -55,4 +60,16 @@ extern int32_t configuration_check(); extern FrameType_t GetCurrentFrameType(); +/** + * Attach a custom hook to the sanity check process + * @param hook a custom hook function + */ +extern void SANITYCHECK_AttachHook(SANITYCHECK_CustomHook_function *hook); + +/** + * Detach a custom hook to the sanity check process + * @param hook a custom hook function + */ +extern void SANITYCHECK_DetachHook(SANITYCHECK_CustomHook_function *hook); + #endif /* SANITYCHECK_H */ diff --git a/flight/libraries/inc/sha1.h b/flight/libraries/inc/sha1.h new file mode 100644 index 000000000..fbf18b137 --- /dev/null +++ b/flight/libraries/inc/sha1.h @@ -0,0 +1,37 @@ +/* $NetBSD: sha1.h,v 1.14 2009/11/06 20:31:19 joerg Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SYS_SHA1_H_ +#define _SYS_SHA1_H_ + +#include +#include + +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH 41 + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + uint8_t buffer[64]; +} SHA1_CTX; + +__BEGIN_DECLS +void SHA1Transform(uint32_t[5], const uint8_t[64]); +void SHA1Init(SHA1_CTX *); +void SHA1Update(SHA1_CTX *, const uint8_t *, unsigned int); +void SHA1Final(uint8_t[SHA1_DIGEST_LENGTH], SHA1_CTX *); +#ifndef _KERNEL +char *SHA1End(SHA1_CTX *, char *); +char *SHA1FileChunk(const char *, char *, off_t, off_t); +char *SHA1File(const char *, char *); +char *SHA1Data(const uint8_t *, size_t, char *); +#endif /* _KERNEL */ +__END_DECLS + +#endif /* _SYS_SHA1_H_ */ diff --git a/flight/libraries/sanitycheck.c b/flight/libraries/sanitycheck.c index 85c074ef9..61950cbd9 100644 --- a/flight/libraries/sanitycheck.c +++ b/flight/libraries/sanitycheck.c @@ -45,10 +45,18 @@ // a number of useful macros #define ADDSEVERITY(check) severity = (severity != SYSTEMALARMS_ALARM_OK ? severity : ((check) ? SYSTEMALARMS_ALARM_OK : SYSTEMALARMS_ALARM_CRITICAL)) +// private types +typedef struct SANITYCHECK_CustomHookInstance { + SANITYCHECK_CustomHook_function *hook; + struct SANITYCHECK_CustomHookInstance *next; + bool enabled; +} SANITYCHECK_CustomHookInstance; // ! Check a stabilization mode switch position for safety static bool check_stabilization_settings(int index, bool multirotor, bool coptercontrol, bool gpsassisted); +SANITYCHECK_CustomHookInstance *hooks = 0; + /** * Run a preflight check over the hardware configuration * and currently active modules @@ -176,6 +184,20 @@ int32_t configuration_check() severity = SYSTEMALARMS_ALARM_WARNING; } + // query sanity check hooks + if (severity == SYSTEMALARMS_ALARM_OK) { + SANITYCHECK_CustomHookInstance *instance = NULL; + LL_FOREACH(hooks, instance) { + if (instance->enabled) { + alarmstatus = instance->hook(); + if (alarmstatus != SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE) { + severity = SYSTEMALARMS_ALARM_WARNING; + break; + } + } + } + } + if (severity != SYSTEMALARMS_ALARM_OK) { ExtendedAlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, severity, alarmstatus, alarmsubstatus); } else { @@ -270,6 +292,7 @@ static bool check_stabilization_settings(int index, bool multirotor, bool copter // and is the same for STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL // (this is checked at compile time by static constraint manualcontrol.h) + return true; } @@ -314,3 +337,39 @@ FrameType_t GetCurrentFrameType() // anyway it should not reach here return FRAME_TYPE_CUSTOM; } + +void SANITYCHECK_AttachHook(SANITYCHECK_CustomHook_function *hook) +{ + PIOS_Assert(hook); + SANITYCHECK_CustomHookInstance *instance = NULL; + + // Check whether there is an existing instance and enable it + LL_FOREACH(hooks, instance) { + if (instance->hook == hook) { + instance->enabled = true; + return; + } + } + + // No existing instance found, attach this new one + instance = (SANITYCHECK_CustomHookInstance *)pios_malloc(sizeof(SANITYCHECK_CustomHookInstance)); + PIOS_Assert(instance); + instance->hook = hook; + instance->next = NULL; + instance->enabled = true; + LL_APPEND(hooks, instance); +} + +void SANITYCHECK_DetachHook(SANITYCHECK_CustomHook_function *hook) +{ + if (!hooks) { + return; + } + SANITYCHECK_CustomHookInstance *instance = NULL; + LL_FOREACH(hooks, instance) { + if (instance->hook == hook) { + instance->enabled = false; + return; + } + } +} diff --git a/flight/libraries/sha1.c b/flight/libraries/sha1.c new file mode 100644 index 000000000..82bfe060f --- /dev/null +++ b/flight/libraries/sha1.c @@ -0,0 +1,279 @@ +/* $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ */ +/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#define SHA1HANDSOFF /* Copies data before messing with it. */ + +#include + +#if defined(_KERNEL) || defined(_STANDALONE) +__KERNEL_RCSID(0, "$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $"); + +#include + +#else + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $"); +#endif /* LIBC_SCCS and not lint */ + +// #include "namespace.h" +#include +#include + +#endif + +#include +#include + + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#if !HAVE_SHA1_H + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +#if BYTE_ORDER == LITTLE_ENDIAN +# define blk0(i) \ + (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ + | (rol(block->l[i], 8) & 0x00FF00FF)) +#else +# define blk0(i) block->l[i] +#endif +#define blk(i) \ + (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \ + ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); w = rol(w, 30); +#define R1(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); w = rol(w, 30); +#define R2(v, w, x, y, z, i) z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); +#define R3(v, w, x, y, z, i) z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); w = rol(w, 30); +#define R4(v, w, x, y, z, i) z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); w = rol(w, 30); + + +#if !defined(_KERNEL) && !defined(_STANDALONE) +#if defined(__weak_alias) +__weak_alias(SHA1Transform, _SHA1Transform) +__weak_alias(SHA1Init, _SHA1Init) +__weak_alias(SHA1Update, _SHA1Update) +__weak_alias(SHA1Final, _SHA1Final) +#endif +#endif + +typedef union { + uint8_t c[64]; + uint32_t l[16]; +} CHAR64LONG16; + +/* old sparc64 gcc could not compile this */ +#undef SPARC64_GCC_WORKAROUND +#if defined(__sparc64__) && defined(__GNUC__) && __GNUC__ < 3 +#define SPARC64_GCC_WORKAROUND +#endif + +#ifdef SPARC64_GCC_WORKAROUND +void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); + +#define nR0(v, w, x, y, z, i) R0(*v, *w, *x, *y, *z, i) +#define nR1(v, w, x, y, z, i) R1(*v, *w, *x, *y, *z, i) +#define nR2(v, w, x, y, z, i) R2(*v, *w, *x, *y, *z, i) +#define nR3(v, w, x, y, z, i) R3(*v, *w, *x, *y, *z, i) +#define nR4(v, w, x, y, z, i) R4(*v, *w, *x, *y, *z, i) + +void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR0(a, b, c, d, e, 0); nR0(e, a, b, c, d, 1); nR0(d, e, a, b, c, 2); nR0(c, d, e, a, b, 3); + nR0(b, c, d, e, a, 4); nR0(a, b, c, d, e, 5); nR0(e, a, b, c, d, 6); nR0(d, e, a, b, c, 7); + nR0(c, d, e, a, b, 8); nR0(b, c, d, e, a, 9); nR0(a, b, c, d, e, 10); nR0(e, a, b, c, d, 11); + nR0(d, e, a, b, c, 12); nR0(c, d, e, a, b, 13); nR0(b, c, d, e, a, 14); nR0(a, b, c, d, e, 15); + nR1(e, a, b, c, d, 16); nR1(d, e, a, b, c, 17); nR1(c, d, e, a, b, 18); nR1(b, c, d, e, a, 19); +} + +void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR2(a, b, c, d, e, 20); nR2(e, a, b, c, d, 21); nR2(d, e, a, b, c, 22); nR2(c, d, e, a, b, 23); + nR2(b, c, d, e, a, 24); nR2(a, b, c, d, e, 25); nR2(e, a, b, c, d, 26); nR2(d, e, a, b, c, 27); + nR2(c, d, e, a, b, 28); nR2(b, c, d, e, a, 29); nR2(a, b, c, d, e, 30); nR2(e, a, b, c, d, 31); + nR2(d, e, a, b, c, 32); nR2(c, d, e, a, b, 33); nR2(b, c, d, e, a, 34); nR2(a, b, c, d, e, 35); + nR2(e, a, b, c, d, 36); nR2(d, e, a, b, c, 37); nR2(c, d, e, a, b, 38); nR2(b, c, d, e, a, 39); +} + +void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR3(a, b, c, d, e, 40); nR3(e, a, b, c, d, 41); nR3(d, e, a, b, c, 42); nR3(c, d, e, a, b, 43); + nR3(b, c, d, e, a, 44); nR3(a, b, c, d, e, 45); nR3(e, a, b, c, d, 46); nR3(d, e, a, b, c, 47); + nR3(c, d, e, a, b, 48); nR3(b, c, d, e, a, 49); nR3(a, b, c, d, e, 50); nR3(e, a, b, c, d, 51); + nR3(d, e, a, b, c, 52); nR3(c, d, e, a, b, 53); nR3(b, c, d, e, a, 54); nR3(a, b, c, d, e, 55); + nR3(e, a, b, c, d, 56); nR3(d, e, a, b, c, 57); nR3(c, d, e, a, b, 58); nR3(b, c, d, e, a, 59); +} + +void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR4(a, b, c, d, e, 60); nR4(e, a, b, c, d, 61); nR4(d, e, a, b, c, 62); nR4(c, d, e, a, b, 63); + nR4(b, c, d, e, a, 64); nR4(a, b, c, d, e, 65); nR4(e, a, b, c, d, 66); nR4(d, e, a, b, c, 67); + nR4(c, d, e, a, b, 68); nR4(b, c, d, e, a, 69); nR4(a, b, c, d, e, 70); nR4(e, a, b, c, d, 71); + nR4(d, e, a, b, c, 72); nR4(c, d, e, a, b, 73); nR4(b, c, d, e, a, 74); nR4(a, b, c, d, e, 75); + nR4(e, a, b, c, d, 76); nR4(d, e, a, b, c, 77); nR4(c, d, e, a, b, 78); nR4(b, c, d, e, a, 79); +} +#endif /* ifdef SPARC64_GCC_WORKAROUND */ + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void SHA1Transform(uint32_t state[5], const uint8_t buffer[64]) +{ + uint32_t a, b, c, d, e; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; +#endif + +#ifdef SHA1HANDSOFF + block = &workspace; + (void)memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *)(void *)buffer; +#endif + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + +#ifdef SPARC64_GCC_WORKAROUND + do_R01(&a, &b, &c, &d, &e, block); + do_R2(&a, &b, &c, &d, &e, block); + do_R3(&a, &b, &c, &d, &e, block); + do_R4(&a, &b, &c, &d, &e, block); +#else + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); +#endif /* ifdef SPARC64_GCC_WORKAROUND */ + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* + * SHA1Init - Initialize new context + */ +void SHA1Init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* + * Run your data through this. + */ +void SHA1Update(SHA1_CTX *context, const uint8_t *data, unsigned int len) +{ + unsigned int i, j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) { + context->count[1] += (len >> 29) + 1; + } + j = (j >> 3) & 63; + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } else { + i = 0; + } + (void)memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* + * Add padding and return the message digest. + */ +void SHA1Final(uint8_t digest[20], SHA1_CTX *context) +{ + unsigned int i; + uint8_t finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (const uint8_t *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (const uint8_t *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + if (digest) { + for (i = 0; i < 20; i++) { + digest[i] = (uint8_t) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + } +} + +#endif /* HAVE_SHA1_H */ diff --git a/flight/modules/Actuator/actuator.c b/flight/modules/Actuator/actuator.c index 7cc78c7b1..891537bd6 100644 --- a/flight/modules/Actuator/actuator.c +++ b/flight/modules/Actuator/actuator.c @@ -53,20 +53,23 @@ static int8_t counter; #endif // Private constants -#define MAX_QUEUE_SIZE 2 +#define MAX_QUEUE_SIZE 2 #if defined(PIOS_ACTUATOR_STACK_SIZE) -#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE +#define STACK_SIZE_BYTES PIOS_ACTUATOR_STACK_SIZE #else -#define STACK_SIZE_BYTES 1312 +#define STACK_SIZE_BYTES 1312 #endif -#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver -#define FAILSAFE_TIMEOUT_MS 100 -#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM +#define TASK_PRIORITY (tskIDLE_PRIORITY + 4) // device driver +#define FAILSAFE_TIMEOUT_MS 100 +#define MAX_MIX_ACTUATORS ACTUATORCOMMAND_CHANNEL_NUMELEM -#define CAMERA_BOOT_DELAY_MS 7000 +#define CAMERA_BOOT_DELAY_MS 7000 +#define ACTUATOR_ONESHOT125_CLOCK 2000000 +#define ACTUATOR_ONESHOT125_PULSE_SCALE 4 +#define ACTUATOR_PWM_CLOCK 1000000 // Private types @@ -74,8 +77,9 @@ static int8_t counter; static xQueueHandle queue; static xTaskHandle taskHandle; -static float lastResult[MAX_MIX_ACTUATORS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static float filterAccumulator[MAX_MIX_ACTUATORS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static float lastResult[MAX_MIX_ACTUATORS] = { 0 }; +static float filterAccumulator[MAX_MIX_ACTUATORS] = { 0 }; +static uint8_t pinsMode[MAX_MIX_ACTUATORS]; // used to inform the actuator thread that actuator update rate is changed static volatile bool actuator_settings_updated; // used to inform the actuator thread that mixer settings are changed @@ -436,7 +440,6 @@ static void actuatorTask(__attribute__((unused)) void *parameters) if (command.UpdateTime > command.MaxUpdateTime) { command.MaxUpdateTime = command.UpdateTime; } - // Update output object ActuatorCommandSet(&command); // Update in case read only (eg. during servo configuration) @@ -454,6 +457,8 @@ static void actuatorTask(__attribute__((unused)) void *parameters) success &= set_channel(n, command.Channel[n], &actuatorSettings); } + PIOS_Servo_Update(); + if (!success) { command.NumFailedUpdates++; ActuatorCommandSet(&command); @@ -476,11 +481,11 @@ float ProcessMixer(const int index, const float curve1, const float curve2, const Mixer_t *mixers = (Mixer_t *)&mixerSettings->Mixer1Type; // pointer to array of mixers in UAVObjects const Mixer_t *mixer = &mixers[index]; - float result = (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE1] / 128.0f) * curve1) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE2] / 128.0f) * curve2) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL] / 128.0f) * desired->Roll) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH] / 128.0f) * desired->Pitch) + - (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW] / 128.0f) * desired->Yaw); + float result = ((((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE1]) * curve1) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE2]) * curve2) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL]) * desired->Roll) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH]) * desired->Pitch) + + (((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW]) * desired->Yaw)) / 128.0f; // note: no feedforward for reversable motors yet for safety reasons if (mixer->type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { @@ -615,6 +620,8 @@ static void setFailsafe(const ActuatorSettingsData *actuatorSettings, const Mixe for (int n = 0; n < ACTUATORCOMMAND_CHANNEL_NUMELEM; ++n) { set_channel(n, Channel[n], actuatorSettings); } + // Send the updated command + PIOS_Servo_Update(); // Update output object's parts that we changed ActuatorCommandChannelSet(Channel); @@ -730,8 +737,19 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet return true; case ACTUATORSETTINGS_CHANNELTYPE_PWM: - PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); + { + uint8_t mode = pinsMode[actuatorSettings->ChannelAddr[mixer_channel]]; + switch (mode) { + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + // Remap 1000-2000 range to 125-250 + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value / ACTUATOR_ONESHOT125_PULSE_SCALE); + break; + default: + PIOS_Servo_Set(actuatorSettings->ChannelAddr[mixer_channel], value); + break; + } return true; + } #if defined(PIOS_INCLUDE_I2C_ESC) case ACTUATORSETTINGS_CHANNELTYPE_MK: @@ -754,18 +772,57 @@ static bool set_channel(uint8_t mixer_channel, uint16_t value, const ActuatorSet */ static void actuator_update_rate_if_changed(const ActuatorSettingsData *actuatorSettings, bool force_update) { - static uint16_t prevChannelUpdateFreq[ACTUATORSETTINGS_CHANNELUPDATEFREQ_NUMELEM]; + static uint16_t prevBankUpdateFreq[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM]; + static uint8_t prevBankMode[ACTUATORSETTINGS_BANKMODE_NUMELEM]; // check if the any rate setting is changed if (force_update || - memcmp(prevChannelUpdateFreq, - actuatorSettings->ChannelUpdateFreq, - sizeof(prevChannelUpdateFreq)) != 0) { + (memcmp(prevBankUpdateFreq, + actuatorSettings->BankUpdateFreq, + sizeof(prevBankUpdateFreq)) != 0) || + (memcmp(prevBankUpdateFreq, + actuatorSettings->BankMode, + sizeof(prevBankMode)) != 0) + ) { /* Something has changed, apply the settings to HW */ - memcpy(prevChannelUpdateFreq, - actuatorSettings->ChannelUpdateFreq, - sizeof(prevChannelUpdateFreq)); - PIOS_Servo_SetHz(actuatorSettings->ChannelUpdateFreq, ACTUATORSETTINGS_CHANNELUPDATEFREQ_NUMELEM); + memcpy(prevBankUpdateFreq, + actuatorSettings->BankUpdateFreq, + sizeof(prevBankUpdateFreq)); + memcpy(prevBankMode, + actuatorSettings->BankMode, + sizeof(prevBankMode)); + + uint16_t freq[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM]; + uint32_t clock[ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM] = { 0 }; + for (uint8_t i = 0; i < ACTUATORSETTINGS_BANKMODE_NUMELEM; i++) { + PIOS_Servo_SetBankMode(i, + actuatorSettings->BankMode[i] == + ACTUATORSETTINGS_BANKMODE_PWM ? + PIOS_SERVO_BANK_MODE_PWM : + PIOS_SERVO_BANK_MODE_SINGLE_PULSE + ); + switch (actuatorSettings->BankMode[i]) { + case ACTUATORSETTINGS_BANKMODE_ONESHOT125: + freq[i] = 100; // Value must be small enough so CCr isn't update until the PIOS_Servo_Update is triggered + clock[i] = ACTUATOR_ONESHOT125_CLOCK; // Setup an 8MHz timer clock + break; + case ACTUATORSETTINGS_BANKMODE_ONESHOT: + freq[i] = 100; + clock[i] = ACTUATOR_PWM_CLOCK; + break; + default: // PWM + freq[i] = actuatorSettings->BankUpdateFreq[i]; + clock[i] = ACTUATOR_PWM_CLOCK; + break; + } + } + PIOS_Servo_SetHz(freq, clock, ACTUATORSETTINGS_BANKUPDATEFREQ_NUMELEM); + + // retrieve mode from related bank + for (uint8_t i = 0; i < MAX_MIX_ACTUATORS; i++) { + uint8_t bank = PIOS_Servo_GetPinBank(i); + pinsMode[i] = actuatorSettings->BankMode[bank]; + } } } diff --git a/flight/modules/OPLink/oplinkmod.c b/flight/modules/OPLink/oplinkmod.c index be746756c..cc076053a 100644 --- a/flight/modules/OPLink/oplinkmod.c +++ b/flight/modules/OPLink/oplinkmod.c @@ -158,7 +158,6 @@ static void systemTask(__attribute__((unused)) void *parameters) oplinkStatus.RxMissed = radio_stats.rx_missed; oplinkStatus.RxFailure = radio_stats.rx_failure; oplinkStatus.TxDropped = radio_stats.tx_dropped; - oplinkStatus.TxResent = radio_stats.tx_resent; oplinkStatus.TxFailure = radio_stats.tx_failure; oplinkStatus.Resets = radio_stats.resets; oplinkStatus.Timeouts = radio_stats.timeouts; diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index affcf580d..33567d827 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -267,7 +267,6 @@ static void systemTask(__attribute__((unused)) void *parameters) oplinkStatus.RxMissed = radio_stats.rx_missed; oplinkStatus.RxFailure = radio_stats.rx_failure; oplinkStatus.TxDropped = radio_stats.tx_dropped; - oplinkStatus.TxResent = radio_stats.tx_resent; oplinkStatus.TxFailure = radio_stats.tx_failure; oplinkStatus.Resets = radio_stats.resets; oplinkStatus.Timeouts = radio_stats.timeouts; diff --git a/flight/pios/common/pios_rfm22b.c b/flight/pios/common/pios_rfm22b.c index 4aed541ed..36f0c7a96 100644 --- a/flight/pios/common/pios_rfm22b.c +++ b/flight/pios/common/pios_rfm22b.c @@ -47,8 +47,8 @@ // 6-byte (32-bit) preamble .. alternating 0's & 1's // 4-byte (32-bit) sync // 1-byte packet length (number of data bytes to follow) -// 1 byte valid bitmask -// 8 PPM values (0-255) +// 1 byte PPM values LSB (bit 0) +// 8 bytes PPM values MSBs (bit 8:1) // 1 byte CRC // // ***************************************************************** @@ -61,6 +61,7 @@ #include #include #include +#include /* Local Defines */ #define STACK_SIZE_BYTES 200 @@ -73,9 +74,16 @@ #define RFM22B_LINK_QUALITY_THRESHOLD 20 #define RFM22B_DEFAULT_MIN_CHANNEL 0 #define RFM22B_DEFAULT_MAX_CHANNEL 250 -#define RFM22B_DEFAULT_CHANNEL_SET 24 #define RFM22B_PPM_ONLY_DATARATE RFM22_datarate_9600 +// PPM encoding limits +#define RFM22B_PPM_MIN 1 +#define RFM22B_PPM_MAX 511 +#define RFM22B_PPM_INVALID 0 +#define RFM22B_PPM_SCALE 2 +#define RFM22B_PPM_MIN_US 990 +#define RFM22B_PPM_MAX_US (RFM22B_PPM_MIN_US + (RFM22B_PPM_MAX - RFM22B_PPM_MIN) * RFM22B_PPM_SCALE) + // The maximum amount of time without activity before initiating a reset. #define PIOS_RFM22B_SUPERVISOR_TIMEOUT 150 // ms @@ -116,6 +124,9 @@ #define USB_LED_OFF #endif +#define CONNECTED_TIMEOUT (250 / portTICK_RATE_MS) /* ms */ +#define MAX_CHANNELS 32 + /* Local type definitions */ struct pios_rfm22b_transition { @@ -155,21 +166,6 @@ static const uint8_t OUT_FF[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -// The randomized channel list. -static const uint8_t channel_list[] = { - 68, 34, 2, 184, 166, 94, 204, 18, 47, 118, 239, 176, 5, 213, 218, 186, 104, 160, 199, 209, 231, 197, 92, - 191, 88, 129, 40, 19, 93, 200, 156, 14, 247, 182, 193, 194, 208, 210, 248, 76, 244, 48, 179, 105, 25, 74, - 155, 203, 39, 97, 195, 81, 83, 180, 134, 172, 235, 132, 198, 119, 207, 154, 0, 61, 140, 171, 245, 26, 95, - 3, 22, 62, 169, 55, 127, 144, 45, 33, 170, 91, 158, 167, 63, 201, 41, 21, 190, 51, 103, 49, 189, 205, - 240, 89, 181, 149, 6, 157, 249, 230, 115, 72, 163, 17, 29, 99, 28, 117, 219, 73, 78, 53, 69, 216, 161, - 124, 110, 242, 214, 145, 13, 11, 220, 113, 138, 58, 54, 162, 237, 37, 152, 187, 232, 77, 126, 85, 38, 238, - 173, 23, 188, 100, 131, 226, 31, 9, 114, 106, 221, 42, 233, 139, 4, 241, 96, 211, 8, 98, 121, 147, 24, - 217, 27, 87, 122, 125, 135, 148, 178, 71, 206, 57, 141, 35, 30, 246, 159, 16, 32, 15, 229, 20, 12, 223, - 150, 101, 79, 56, 102, 111, 174, 236, 137, 143, 52, 225, 64, 224, 112, 168, 243, 130, 108, 202, 123, 146, 228, - 75, 46, 153, 7, 192, 175, 151, 222, 59, 82, 90, 1, 65, 109, 44, 165, 84, 43, 36, 128, 196, 67, 80, - 136, 86, 70, 234, 66, 185, 10, 164, 177, 116, 50, 107, 183, 215, 212, 60, 227, 133, 120, 14 -}; - /* Local function forwared declarations */ static void pios_rfm22_task(void *parameters); static bool pios_rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev); @@ -207,6 +203,10 @@ static void rfm22_clearLEDs(); // Utility functions. static uint32_t pios_rfm22_time_difference_ms(portTickType start_time, portTickType end_time); static struct pios_rfm22b_dev *pios_rfm22_alloc(void); +static void rfm22_hmac_sha1(const uint8_t *data, size_t len, uint8_t key[SHA1_DIGEST_LENGTH], + uint8_t digest[SHA1_DIGEST_LENGTH]); +static bool rfm22_gen_channels(uint32_t coordid, enum rfm22b_datarate datarate, uint8_t min, + uint8_t max, uint8_t channels[MAX_CHANNELS], uint8_t *clen); // SPI read/write functions static void rfm22_assertCs(struct pios_rfm22b_dev *rfm22b_dev); @@ -331,6 +331,18 @@ static const uint32_t data_rate[] = { 256000, // 256 kbps, 433 MHz, 150 khz freq dev }; +static const uint8_t channel_spacing[] = { + 1, /* 9.6kbps */ + 2, /* 19.2kps */ + 2, /* 32kps */ + 2, /* 57.6kps */ + 2, /* 64kps */ + 3, /* 100kps */ + 4, /* 128kps */ + 4, /* 192kps */ + 4 /* 256kps */ +}; + static const uint8_t reg_1C[] = { 0x01, 0x05, 0x06, 0x95, 0x95, 0x81, 0x88, 0x8B, 0x8D }; // rfm22_if_filter_bandwidth static const uint8_t reg_1D[] = { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 }; // rfm22_afc_loop_gearshift_override @@ -358,7 +370,7 @@ static const uint8_t reg_72[] = { 0x30, 0x48, 0x48, 0x48, 0x48, 0x60, 0x90, 0xCD static const uint8_t packet_time[] = { 80, 40, 25, 15, 13, 10, 8, 6, 5 }; static const uint8_t packet_time_ppm[] = { 26, 25, 25, 15, 13, 10, 8, 6, 5 }; -static const uint8_t num_channels[] = { 4, 4, 4, 6, 8, 8, 10, 12, 16 }; +static const uint8_t num_channels[] = { 32, 32, 32, 32, 32, 32, 32, 32, 32 }; static struct pios_rfm22b_dev *g_rfm22b_dev = NULL; @@ -412,7 +424,6 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu rfm22b_dev->stats.rx_error = 0; rfm22b_dev->stats.rx_missed = 0; rfm22b_dev->stats.tx_dropped = 0; - rfm22b_dev->stats.tx_resent = 0; rfm22b_dev->stats.resets = 0; rfm22b_dev->stats.timeouts = 0; rfm22b_dev->stats.link_quality = 0; @@ -423,7 +434,7 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Initialize the channels. PIOS_RFM22B_SetChannelConfig(*rfm22b_id, RFM22B_DEFAULT_RX_DATARATE, RFM22B_DEFAULT_MIN_CHANNEL, - RFM22B_DEFAULT_MAX_CHANNEL, RFM22B_DEFAULT_CHANNEL_SET, false, false, false, false); + RFM22B_DEFAULT_MAX_CHANNEL, false, false, false, false); // Create the event queue rfm22b_dev->eventQueue = xQueueCreate(EVENT_QUEUE_SIZE, sizeof(enum pios_radio_event)); @@ -566,12 +577,12 @@ void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, enum rfm22b_tx_power tx_pwr) * @param[in] datarate The desired datarate. * @param[in] min_chan The minimum channel. * @param[in] max_chan The maximum channel. - * @param[in] chan_set The "seed" for selecting a channel sequence. * @param[in] coordinator Is this modem an coordinator. * @param[in] ppm_mode Should this modem send/receive ppm packets? * @param[in] oneway Only the coordinator can send packets if true. + * @param[in] ppm_only Should this modem run in ppm only mode? */ -void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datarate, uint8_t min_chan, uint8_t max_chan, uint8_t chan_set, bool coordinator, bool oneway, bool ppm_mode, bool ppm_only) +void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datarate, uint8_t min_chan, uint8_t max_chan, bool coordinator, bool oneway, bool ppm_mode, bool ppm_only) { struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; @@ -596,15 +607,11 @@ void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datar } rfm22b_dev->packet_time = (ppm_mode ? packet_time_ppm[datarate] : packet_time[datarate]); - // Find the first N channels that meet the min/max criteria out of the random channel list. uint8_t num_found = 0; - for (uint16_t i = 0; (i < RFM22B_NUM_CHANNELS) && (num_found < num_channels[datarate]); ++i) { - uint8_t idx = (i + chan_set) % RFM22B_NUM_CHANNELS; - uint8_t chan = channel_list[idx]; - if ((chan >= min_chan) && (chan <= max_chan)) { - rfm22b_dev->channels[num_found++] = chan; - } - } + rfm22_gen_channels(rfm22_destinationID(rfm22b_dev), datarate, min_chan, max_chan, + rfm22b_dev->channels, &num_found); + + rfm22b_dev->num_channels = num_found; // Calculate the maximum packet length from the datarate. float bytes_per_period = (float)data_rate[datarate] * (float)(rfm22b_dev->packet_time - 2) / 9000; @@ -1354,7 +1361,7 @@ static enum pios_radio_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->packet_start_ticks = 0; rfm22b_dev->tx_complete_ticks = 0; rfm22b_dev->rfm22b_state = RFM22B_STATE_INITIALIZING; - rfm22b_dev->on_sync_channel = false; + rfm22b_dev->last_contact = 0; // software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B) rfm22_write_claim(rfm22b_dev, RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); @@ -1725,7 +1732,7 @@ static bool pios_rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev) */ static void rfm22_rxFailure(struct pios_rfm22b_dev *rfm22b_dev) { - rfm22b_dev->stats.rx_failure++; + rfm22b_add_rx_status(rfm22b_dev, RADIO_FAILURE_RX_PACKET); rfm22b_dev->rx_buffer_wr = 0; rfm22b_dev->packet_start_ticks = 0; rfm22b_dev->rfm22b_state = RFM22B_STATE_TRANSITION; @@ -1767,18 +1774,31 @@ static enum pios_radio_event radio_txStart(struct pios_rfm22b_dev *radio_dev) return RADIO_EVENT_RX_MODE; } - // The first byte is a bitmask of valid channels. + // The first byte stores the LSB of each channel p[0] = 0; // Read the PPM input. for (uint8_t i = 0; i < RFM22B_PPM_NUM_CHANNELS; ++i) { int32_t val = radio_dev->ppm[i]; + + // Clamp and translate value, or transmit as reserved "invalid" constant if ((val == PIOS_RCVR_INVALID) || (val == PIOS_RCVR_TIMEOUT)) { - p[i + 1] = 0; + val = RFM22B_PPM_INVALID; + } else if (val > RFM22B_PPM_MAX_US) { + val = RFM22B_PPM_MAX; + } else if (val < RFM22B_PPM_MIN_US) { + val = RFM22B_PPM_MIN; } else { - p[0] |= 1 << i; - p[i + 1] = (val < 1000) ? 0 : ((val >= 1900) ? 255 : (uint8_t)(256 * (val - 1000) / 900)); + val = (val - RFM22B_PPM_MIN_US) / RFM22B_PPM_SCALE + RFM22B_PPM_MIN; } + + // Store LSB + if (val & 1) { + p[0] |= (1 << i); + } + + // Store upper 8 bits in array + p[i + 1] = val >> 1; } // The last byte is a CRC. @@ -1798,8 +1818,8 @@ static enum pios_radio_event radio_txStart(struct pios_rfm22b_dev *radio_dev) len += (radio_dev->tx_out_cb)(radio_dev->tx_out_context, p + len, max_data_len - len, NULL, &need_yield); } - // Always send a packet on the sync channel if this modem is a coordinator. - if ((len == 0) && ((radio_dev->channel_index != 0) || !rfm22_isCoordinator(radio_dev))) { + // Always send a packet if this modem is a coordinator. + if ((len == 0) && !rfm22_isCoordinator(radio_dev)) { return RADIO_EVENT_RX_MODE; } @@ -1921,10 +1941,11 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d if (good_packet || corrected_packet) { for (uint8_t i = 0; i < RFM22B_PPM_NUM_CHANNELS; ++i) { + // Calculate 9-bit value taking the LSB from byte 0 + uint32_t val = (p[i + 1] << 1) + ((p[0] >> i) & 1); // Is this a valid channel? - if (p[0] & (1 << i)) { - uint32_t val = p[i + 1]; - radio_dev->ppm[i] = (uint16_t)(1000 + val * 900 / 256); + if (val != RFM22B_PPM_INVALID) { + radio_dev->ppm[i] = (uint16_t)(RFM22B_PPM_MIN_US + (val - RFM22B_PPM_MIN) * RFM22B_PPM_SCALE); } else { radio_dev->ppm[i] = PIOS_RCVR_INVALID; } @@ -1959,12 +1980,16 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d (radio_dev->rx_in_cb)(radio_dev->rx_in_context, p, data_len, NULL, &rx_need_yield); } - // We only synchronize the clock on packets from our coordinator on the sync channel. - if (!rfm22_isCoordinator(radio_dev) && (radio_dev->rx_destination_id == rfm22_destinationID(radio_dev)) && (radio_dev->channel_index == 0)) { + /* + * If the packet is valid and destined for us we synchronize the clock. + */ + if (!rfm22_isCoordinator(radio_dev) && + radio_dev->rx_destination_id == rfm22_destinationID(radio_dev)) { rfm22_synchronizeClock(radio_dev); radio_dev->stats.link_state = OPLINKSTATUS_LINKSTATE_CONNECTED; - radio_dev->on_sync_channel = false; } + + radio_dev->last_contact = xTaskGetTickCount(); } else { ret_event = RADIO_EVENT_RX_COMPLETE; } @@ -2069,7 +2094,7 @@ static void rfm22_calculateLinkQuality(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->stats.rx_good = 0; rfm22b_dev->stats.rx_corrected = 0; rfm22b_dev->stats.rx_error = 0; - rfm22b_dev->stats.tx_resent = 0; + rfm22b_dev->stats.rx_failure = 0; for (uint8_t i = 0; i < RFM22B_RX_PACKET_STATS_LEN; ++i) { uint32_t val = rfm22b_dev->rx_packet_stats[i]; for (uint8_t j = 0; j < 16; ++j) { @@ -2083,8 +2108,8 @@ static void rfm22_calculateLinkQuality(struct pios_rfm22b_dev *rfm22b_dev) case RADIO_ERROR_RX_PACKET: rfm22b_dev->stats.rx_error++; break; - case RADIO_RESENT_TX_PACKET: - rfm22b_dev->stats.tx_resent++; + case RADIO_FAILURE_RX_PACKET: + rfm22b_dev->stats.rx_failure++; break; } } @@ -2094,7 +2119,7 @@ static void rfm22_calculateLinkQuality(struct pios_rfm22b_dev *rfm22b_dev) // Note: This assumes that the number of packets sampled for the stats is 64. // Using this equation, error and resent packets are counted as -2, and corrected packets are counted as -1. // The range is 0 (all error or resent packets) to 128 (all good packets). - rfm22b_dev->stats.link_quality = 64 + rfm22b_dev->stats.rx_good - rfm22b_dev->stats.rx_error - rfm22b_dev->stats.tx_resent; + rfm22b_dev->stats.link_quality = 64 + rfm22b_dev->stats.rx_good - rfm22b_dev->stats.rx_error - rfm22b_dev->stats.rx_failure; } /** @@ -2160,14 +2185,14 @@ static void rfm22_synchronizeClock(struct pios_rfm22b_dev *rfm22b_dev) portTickType start_time = rfm22b_dev->packet_start_ticks; // This packet was transmitted on channel 0, calculate the time delta that will force us to transmit on channel 0 at the time this packet started. - uint8_t num_chan = num_channels[rfm22b_dev->datarate]; - uint16_t frequency_hop_cycle_time = rfm22b_dev->packet_time * num_chan; + uint16_t frequency_hop_cycle_time = rfm22b_dev->packet_time * rfm22b_dev->num_channels; uint16_t time_delta = start_time % frequency_hop_cycle_time; // Calculate the adjustment for the preamble uint8_t offset = (uint8_t)ceil(35000.0F / data_rate[rfm22b_dev->datarate]); - rfm22b_dev->time_delta = frequency_hop_cycle_time - time_delta + offset; + rfm22b_dev->time_delta = frequency_hop_cycle_time - time_delta + offset + + rfm22b_dev->packet_time * rfm22b_dev->channel_index; } /** @@ -2222,15 +2247,13 @@ static bool rfm22_timeToSend(struct pios_rfm22b_dev *rfm22b_dev) static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev, uint8_t index) { // Make sure we don't index outside of the range. - uint8_t num_chan = num_channels[rfm22b_dev->datarate]; - uint8_t idx = index % num_chan; + uint8_t idx = index % rfm22b_dev->num_channels; // Are we switching to a new channel? if (idx != rfm22b_dev->channel_index) { - // If the on_sync_channel flag is set, it means that we were on the sync channel, but no packet was received, so transition to a non-connected state. - if (!rfm22_isCoordinator(rfm22b_dev) && (rfm22b_dev->channel_index == 0) && rfm22b_dev->on_sync_channel) { - rfm22b_dev->on_sync_channel = false; - + if (!rfm22_isCoordinator(rfm22b_dev) && + pios_rfm22_time_difference_ms(rfm22b_dev->last_contact, xTaskGetTickCount()) >= + CONNECTED_TIMEOUT) { // Set the link state to disconnected. if (rfm22b_dev->stats.link_state == OPLINKSTATUS_LINKSTATE_CONNECTED) { rfm22b_dev->stats.link_state = OPLINKSTATUS_LINKSTATE_DISCONNECTED; @@ -2240,11 +2263,8 @@ static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev, uint8_t ind } } - // Stay on the sync channel. + // Stay on first channel. idx = 0; - } else if (idx == 0) { - // If we're switching to the sync channel, set a flag that can be used to detect if a packet was received. - rfm22b_dev->on_sync_channel = true; } rfm22b_dev->channel_index = idx; @@ -2263,8 +2283,7 @@ static uint8_t rfm22_calcChannelFromClock(struct pios_rfm22b_dev *rfm22b_dev) portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount()); // Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms. // Channel changes occur in the last 2 ms. - uint8_t num_chan = num_channels[rfm22b_dev->datarate]; - uint8_t n = (time / rfm22b_dev->packet_time) % num_chan; + uint8_t n = (time / rfm22b_dev->packet_time) % rfm22b_dev->num_channels; return rfm22_calcChannel(rfm22b_dev, n); } @@ -2553,6 +2572,86 @@ static uint8_t rfm22_read(struct pios_rfm22b_dev *rfm22b_dev, uint8_t addr) return in[1]; } + +static void rfm22_hmac_sha1(const uint8_t *data, size_t len, + uint8_t key[SHA1_DIGEST_LENGTH], + uint8_t digest[SHA1_DIGEST_LENGTH]) +{ + uint8_t ipad[64] = { 0 }; + uint8_t opad[64] = { 0 }; + static SHA1_CTX *ctx; + + ctx = pios_malloc(sizeof(SHA1_CTX)); + + memcpy(ipad, key, SHA1_DIGEST_LENGTH); + memcpy(opad, key, SHA1_DIGEST_LENGTH); + + for (int i = 0; i < 64; i++) { + ipad[i] ^= 0x36; + opad[i] ^= 0x5c; + } + + SHA1Init(ctx); + SHA1Update(ctx, ipad, sizeof(ipad)); + SHA1Update(ctx, data, len); + SHA1Final(digest, ctx); + + SHA1Init(ctx); + SHA1Update(ctx, opad, sizeof(opad)); + SHA1Update(ctx, digest, SHA1_DIGEST_LENGTH); + SHA1Final(digest, ctx); + + pios_free(ctx); +} + +static bool rfm22_gen_channels(uint32_t coordid, enum rfm22b_datarate rate, uint8_t min, + uint8_t max, uint8_t channels[MAX_CHANNELS], uint8_t *clen) +{ + uint32_t data = 0; + uint8_t cpos = 0; + uint8_t chan_range = (max / channel_spacing[rate] - min / channel_spacing[rate]) + 1; + uint8_t key[SHA1_DIGEST_LENGTH] = { 0 }; + uint8_t digest[SHA1_DIGEST_LENGTH]; + uint8_t *all_channels; + + all_channels = pios_malloc(RFM22B_NUM_CHANNELS); + + memcpy(key, &coordid, sizeof(coordid)); + + for (int i = 0; i < chan_range; i++) { + all_channels[i] = min / channel_spacing[rate] + i; + } + + int j = SHA1_DIGEST_LENGTH; + for (int i = 0; i < chan_range && i < MAX_CHANNELS; i++) { + uint8_t rnd; + uint8_t r; + uint8_t tmp; + + if (j == SHA1_DIGEST_LENGTH) { + rfm22_hmac_sha1((uint8_t *)&data, sizeof(data), key, digest); + j = 0; + data++; + } + rnd = digest[j]; + j++; + r = rnd % (chan_range - i) + i; + tmp = all_channels[i]; + all_channels[i] = all_channels[r]; + all_channels[r] = tmp; + } + + for (int i = 0; i < chan_range && cpos < MAX_CHANNELS; i++, cpos++) { + channels[cpos] = all_channels[i] * channel_spacing[rate]; + } + + *clen = cpos & 0xfe; + + pios_free(all_channels); + + return *clen > 0; +} + #endif /* PIOS_INCLUDE_RFM22B */ /** diff --git a/flight/pios/inc/pios_pwm.h b/flight/pios/inc/pios_pwm.h index 3552319c9..da3de8409 100644 --- a/flight/pios/inc/pios_pwm.h +++ b/flight/pios/inc/pios_pwm.h @@ -30,4 +30,6 @@ #ifndef PIOS_PWM_H #define PIOS_PWM_H +#define PIOS_PWM_VALID_RANGE_MAX 2250 +#define PIOS_PWM_VALID_RANGE_MIN 750 #endif /* PIOS_PWM_H */ diff --git a/flight/pios/inc/pios_rfm22b.h b/flight/pios/inc/pios_rfm22b.h index b6001ba38..49af876b0 100644 --- a/flight/pios/inc/pios_rfm22b.h +++ b/flight/pios/inc/pios_rfm22b.h @@ -90,7 +90,6 @@ struct rfm22b_stats { uint8_t rx_missed; uint8_t rx_failure; uint8_t tx_dropped; - uint8_t tx_resent; uint8_t tx_failure; uint8_t resets; uint8_t timeouts; @@ -104,7 +103,7 @@ struct rfm22b_stats { extern int32_t PIOS_RFM22B_Init(uint32_t *rfb22b_id, uint32_t spi_id, uint32_t slave_num, const struct pios_rfm22b_cfg *cfg); extern void PIOS_RFM22B_Reinit(uint32_t rfb22b_id); extern void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, enum rfm22b_tx_power tx_pwr); -extern void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datarate, uint8_t min_chan, uint8_t max_chan, uint8_t chan_set, bool coordinator, bool oneway, bool ppm_mode, bool ppm_only); +extern void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datarate, uint8_t min_chan, uint8_t max_chan, bool coordinator, bool oneway, bool ppm_mode, bool ppm_only); extern void PIOS_RFM22B_SetCoordinatorID(uint32_t rfm22b_id, uint32_t coord_id); extern uint32_t PIOS_RFM22B_DeviceID(uint32_t rfb22b_id); extern void PIOS_RFM22B_GetStats(uint32_t rfm22b_id, struct rfm22b_stats *stats); diff --git a/flight/pios/inc/pios_rfm22b_priv.h b/flight/pios/inc/pios_rfm22b_priv.h index bacc2dcda..47cf9d5c0 100644 --- a/flight/pios/inc/pios_rfm22b_priv.h +++ b/flight/pios/inc/pios_rfm22b_priv.h @@ -40,7 +40,7 @@ // ************************************ #define RFM22B_MAX_PACKET_LEN 64 -#define RFM22B_NUM_CHANNELS 250 +#define RFM22B_NUM_CHANNELS 251 // ************************************ @@ -578,7 +578,7 @@ enum pios_rfm22b_rx_packet_status { RADIO_GOOD_RX_PACKET = 0x00, RADIO_CORRECTED_RX_PACKET = 0x01, RADIO_ERROR_RX_PACKET = 0x2, - RADIO_RESENT_TX_PACKET = 0x3 + RADIO_FAILURE_RX_PACKET = 0x3 }; typedef struct { @@ -780,7 +780,7 @@ struct pios_rfm22b_dev { portTickType packet_start_ticks; portTickType tx_complete_ticks; portTickType time_delta; - bool on_sync_channel; + portTickType last_contact; }; diff --git a/flight/pios/inc/pios_servo.h b/flight/pios/inc/pios_servo.h index fd905edbe..f3e9621ad 100644 --- a/flight/pios/inc/pios_servo.h +++ b/flight/pios/inc/pios_servo.h @@ -30,9 +30,17 @@ #ifndef PIOS_SERVO_H #define PIOS_SERVO_H +/* Global types */ +enum pios_servo_bank_mode { + PIOS_SERVO_BANK_MODE_PWM = 0, + PIOS_SERVO_BANK_MODE_SINGLE_PULSE = 1 +}; /* Public Functions */ -extern void PIOS_Servo_SetHz(const uint16_t *update_rates, uint8_t banks); +extern void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks); extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position); +extern void PIOS_Servo_Update(); +extern void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode); +extern uint8_t PIOS_Servo_GetPinBank(uint8_t pin); #endif /* PIOS_SERVO_H */ diff --git a/flight/pios/posix/pios_servo.c b/flight/pios/posix/pios_servo.c index c3b4ba05b..ae00eaa04 100644 --- a/flight/pios/posix/pios_servo.c +++ b/flight/pios/posix/pios_servo.c @@ -43,13 +43,13 @@ static volatile uint16_t ServoPosition[PIOS_SERVO_NUM_TIMERS]; */ void PIOS_Servo_Init(void) {} - /** * Set the servo update rate (Max 500Hz) - * \param[in] onetofour Rate for outputs 1 to 4 (Hz) - * \param[in] fivetoeight Rate for outputs 5 to 8 (Hz) + * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz + * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *banks, uint8_t num_banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) {} /** diff --git a/flight/pios/stm32f10x/pios_pwm.c b/flight/pios/stm32f10x/pios_pwm.c index a583414bd..3c876d22f 100644 --- a/flight/pios/stm32f10x/pios_pwm.c +++ b/flight/pios/stm32f10x/pios_pwm.c @@ -209,7 +209,9 @@ static void PIOS_PWM_tim_overflow_cb(__attribute__((unused)) uint32_t tim_id, ui /* Channel out of range */ return; } - + if (!pwm_dev->CaptureState[channel]) { + return; + } pwm_dev->us_since_update[channel] += count; if (pwm_dev->us_since_update[channel] >= PWM_SUPERVISOR_TIMEOUT) { pwm_dev->CaptureState[channel] = 0; @@ -256,16 +258,19 @@ static void PIOS_PWM_tim_edge_cb(__attribute__((unused)) uint32_t tim_id, uint32 TIM_ICInitStructure.TIM_Channel = chan->timer_chan; TIM_ICInit(chan->timer, &TIM_ICInitStructure); } else { + uint32_t value = 0; /* Capture computation */ - if (pwm_dev->FallValue[chan_idx] > pwm_dev->RiseValue[chan_idx]) { - pwm_dev->CaptureValue[chan_idx] = (pwm_dev->FallValue[chan_idx] - pwm_dev->RiseValue[chan_idx]); - } else { - pwm_dev->CaptureValue[chan_idx] = ((chan->timer->ARR - pwm_dev->RiseValue[chan_idx]) + pwm_dev->FallValue[chan_idx]); + value = pwm_dev->us_since_update[chan_idx] + (pwm_dev->FallValue[chan_idx] - pwm_dev->RiseValue[chan_idx]); + + // From time to time glitches happens. Most of the observed case are related to missing or spurious overflows + // happening when they are triggered very close each other. + // The following workaround prevents them to cause troubles by filtering unacceptable values + if (PIOS_PWM_VALID_RANGE_MAX > value && PIOS_PWM_VALID_RANGE_MIN < value) { + pwm_dev->CaptureValue[chan_idx] = value; } - /* Switch states */ - pwm_dev->CaptureState[chan_idx] = 0; - + pwm_dev->CaptureState[chan_idx] = 0; + pwm_dev->us_since_update[chan_idx] = 0; /* Increase supervisor counter */ pwm_dev->CapCounter[chan_idx]++; diff --git a/flight/pios/stm32f10x/pios_servo.c b/flight/pios/stm32f10x/pios_servo.c index a0ea16916..f0a11d8e2 100644 --- a/flight/pios/stm32f10x/pios_servo.c +++ b/flight/pios/stm32f10x/pios_servo.c @@ -39,6 +39,17 @@ static const struct pios_servo_cfg *servo_cfg; +// determine if the related timer will work in synchronous (or OneShot/OneShot125) One Pulse mode. +// static uint8_t pios_servo_bank_mode[PIOS_SERVO_BANKS] = { 0 }; + +// timer associated to each bank +static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; + +// index of bank used for each pin +static uint8_t *pios_servo_pin_bank; + +#define PIOS_SERVO_TIMER_CLOCK 1000000 + /** * Initialise Servos */ @@ -52,10 +63,36 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /* Store away the requested configuration */ servo_cfg = cfg; + pios_servo_pin_bank = pios_malloc(sizeof(uint8_t) * cfg->num_channels); + uint8_t bank = 0; /* Configure the channels to be in output compare mode */ for (uint8_t i = 0; i < cfg->num_channels; i++) { - const struct pios_tim_channel *chan = &cfg->channels[i]; + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + bool new = true; + /* See if any previous channels use that same timer */ + for (uint8_t j = 0; (j < i) && new; j++) { + new &= chan->timer != servo_cfg->channels[j].timer; + } + + if (new) { + PIOS_Assert(bank < PIOS_SERVO_BANKS); + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } + pios_servo_bank_timer[bank] = chan->timer; + + PIOS_Assert(bank < PIOS_SERVO_BANKS); + + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } + bank++; + } /* Set up for output compare function */ switch (chan->timer_chan) { @@ -88,10 +125,12 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) { + PIOS_Assert(banks <= PIOS_SERVO_BANKS); if (!servo_cfg) { return; } @@ -99,23 +138,18 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; - uint8_t set = 0; + for (uint8_t i = 0; i < banks && i < PIOS_SERVO_BANKS; i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer) { + uint32_t new_clock = PIOS_SERVO_TIMER_CLOCK; + if (clock[i]) { + new_clock = clock[i]; + } + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / new_clock) - 1; + TIM_TimeBaseStructure.TIM_Period = ((new_clock / speeds[i]) - 1); - for (uint8_t i = 0; (i < servo_cfg->num_channels) && (set < banks); i++) { - bool new = true; - const struct pios_tim_channel *chan = &servo_cfg->channels[i]; - - /* See if any previous channels use that same timer */ - for (uint8_t j = 0; (j < i) && new; j++) { - new &= chan->timer != servo_cfg->channels[j].timer; - } - - if (new) { - TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1); - TIM_TimeBaseInit(chan->timer, &TIM_TimeBaseStructure); - set++; + TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } } @@ -150,4 +184,27 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) } } +void PIOS_Servo_Update() +{ + /* + for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer) { + TIM_Cmd((TIM_TypeDef *)timer, ENABLE); + } + } + */ +} + +void PIOS_Servo_SetBankMode(__attribute__((unused)) uint8_t bank, __attribute__((unused)) uint8_t mode) {} + +uint8_t PIOS_Servo_GetPinBank(uint8_t pin) +{ + if (pin < servo_cfg->num_channels) { + return pios_servo_pin_bank[pin]; + } else { + return 0; + } +} + #endif /* PIOS_INCLUDE_SERVO */ diff --git a/flight/pios/stm32f10x/pios_tim.c b/flight/pios/stm32f10x/pios_tim.c index d585c3fd7..4df093299 100644 --- a/flight/pios/stm32f10x/pios_tim.c +++ b/flight/pios/stm32f10x/pios_tim.c @@ -159,6 +159,16 @@ out_fail: static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer) { + /* Check for an overflow event on this timer */ + bool overflow_event = 0; + uint16_t overflow_count = false; + + if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) { + TIM_ClearITPendingBit(timer, TIM_IT_Update); + overflow_count = timer->ARR; + overflow_event = true; + } + /* Iterate over all registered clients of the TIM layer to find channels on this timer */ for (uint8_t i = 0; i < pios_tim_num_devs; i++) { const struct pios_tim_dev *tim_dev = &pios_tim_devs[i]; @@ -168,18 +178,6 @@ static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer) continue; } - /* Check for an overflow event on this timer */ - bool overflow_event; - uint16_t overflow_count; - if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) { - TIM_ClearITPendingBit(timer, TIM_IT_Update); - overflow_count = timer->ARR; - overflow_event = true; - } else { - overflow_count = 0; - overflow_event = false; - } - for (uint8_t j = 0; j < tim_dev->num_channels; j++) { const struct pios_tim_channel *chan = &tim_dev->channels[j]; @@ -251,11 +249,11 @@ static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer) * get the order wrong, our pulse width calculations could be off by up * to ARR ticks. That could be bad. * - * Heuristic: If the edge_count is < 16 ticks above zero then we assume the + * Heuristic: If the edge_count is < 32 ticks above zero then we assume the * edge happened just after the overflow. */ - if (edge_count < 16) { + if (edge_count < 32) { /* Call the overflow callback first */ if (tim_dev->callbacks->overflow) { (*tim_dev->callbacks->overflow)((uint32_t)tim_dev, @@ -300,67 +298,6 @@ static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer) } } } -#if 0 -uint16_t val = 0; -for (uint8_t i = 0; i < pios_pwm_cfg.num_channels; i++) { - struct pios_pwm_channel channel = pios_pwm_cfg.channels[i]; - if ((channel.timer == timer) && (TIM_GetITStatus(channel.timer, channel.ccr) == SET)) { - TIM_ClearITPendingBit(channel.timer, channel.ccr); - - switch (channel.channel) { - case TIM_Channel_1: - val = TIM_GetCapture1(channel.timer); - break; - case TIM_Channel_2: - val = TIM_GetCapture2(channel.timer); - break; - case TIM_Channel_3: - val = TIM_GetCapture3(channel.timer); - break; - case TIM_Channel_4: - val = TIM_GetCapture4(channel.timer); - break; - } - - if (CaptureState[i] == 0) { - RiseValue[i] = val; - } else { - FallValue[i] = val; - } - - // flip state machine and capture value here - /* Simple rise or fall state machine */ - TIM_ICInitTypeDef TIM_ICInitStructure = pios_pwm_cfg.tim_ic_init; - if (CaptureState[i] == 0) { - /* Switch states */ - CaptureState[i] = 1; - - /* Switch polarity of input capture */ - TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; - TIM_ICInitStructure.TIM_Channel = channel.channel; - TIM_ICInit(channel.timer, &TIM_ICInitStructure); - } else { - /* Capture computation */ - if (FallValue[i] > RiseValue[i]) { - CaptureValue[i] = (FallValue[i] - RiseValue[i]); - } else { - CaptureValue[i] = ((channel.timer->ARR - RiseValue[i]) + FallValue[i]); - } - - /* Switch states */ - CaptureState[i] = 0; - - /* Increase supervisor counter */ - CapCounter[i]++; - - /* Switch polarity of input capture */ - TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; - TIM_ICInitStructure.TIM_Channel = channel.channel; - TIM_ICInit(channel.timer, &TIM_ICInitStructure); - } - } -} -#endif /* if 0 */ /* Bind Interrupt Handlers * diff --git a/flight/pios/stm32f4xx/pios_servo.c b/flight/pios/stm32f4xx/pios_servo.c index 32803a57b..7e66c09e2 100644 --- a/flight/pios/stm32f4xx/pios_servo.c +++ b/flight/pios/stm32f4xx/pios_servo.c @@ -39,6 +39,19 @@ static const struct pios_servo_cfg *servo_cfg; +// determine if the related timer will work in synchronous (or OneShot/OneShot125) One Pulse mode. +static uint8_t pios_servo_bank_mode[PIOS_SERVO_BANKS] = { 0 }; +// used to skip updates when pulse length is higher than update cycle +static uint16_t pios_servo_bank_next_update[PIOS_SERVO_BANKS] = { 0 }; +static uint16_t pios_servo_bank_max_pulse[PIOS_SERVO_BANKS] = { 0 }; +// timer associated to each bank +static TIM_TypeDef *pios_servo_bank_timer[PIOS_SERVO_BANKS] = { 0 }; + +// index of bank used for each pin +static uint8_t *pios_servo_pin_bank; + +#define PIOS_SERVO_TIMER_CLOCK 1000000 +#define PIOS_SERVO_SAFE_MARGIN 50 /** * Initialise Servos */ @@ -52,46 +65,141 @@ int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg) /* Store away the requested configuration */ servo_cfg = cfg; + pios_servo_pin_bank = pios_malloc(sizeof(uint8_t) * cfg->num_channels); - /* Configure the channels to be in output compare mode */ - for (uint8_t i = 0; i < cfg->num_channels; i++) { - const struct pios_tim_channel *chan = &cfg->channels[i]; + uint8_t bank = 0; + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + bool new = true; + /* See if any previous channels use that same timer */ + for (uint8_t j = 0; (j < i) && new; j++) { + new &= chan->timer != servo_cfg->channels[j].timer; + } + + if (new) { + PIOS_Assert(bank < PIOS_SERVO_BANKS); + for (uint8_t j = i; j < servo_cfg->num_channels; j++) { + if (servo_cfg->channels[j].timer == chan->timer) { + pios_servo_pin_bank[j] = bank; + } + } + pios_servo_bank_timer[bank] = chan->timer; + + TIM_ARRPreloadConfig(chan->timer, ENABLE); + TIM_CtrlPWMOutputs(chan->timer, ENABLE); + TIM_Cmd(chan->timer, DISABLE); + + bank++; + } /* Set up for output compare function */ switch (chan->timer_chan) { case TIM_Channel_1: - TIM_OC1Init(chan->timer, &cfg->tim_oc_init); + TIM_OC1Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_2: - TIM_OC2Init(chan->timer, &cfg->tim_oc_init); + TIM_OC2Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_3: - TIM_OC3Init(chan->timer, &cfg->tim_oc_init); + TIM_OC3Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_4: - TIM_OC4Init(chan->timer, &cfg->tim_oc_init); + TIM_OC4Init(chan->timer, &servo_cfg->tim_oc_init); TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; } - - TIM_ARRPreloadConfig(chan->timer, ENABLE); - TIM_CtrlPWMOutputs(chan->timer, ENABLE); - TIM_Cmd(chan->timer, ENABLE); } return 0; } +void PIOS_Servo_SetBankMode(uint8_t bank, uint8_t mode) +{ + PIOS_Assert(bank < PIOS_SERVO_BANKS); + pios_servo_bank_mode[bank] = mode; + + if (pios_servo_bank_timer[bank]) { + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + if (pios_servo_pin_bank[i] == bank) { + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + /* Set up for output compare function */ + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_OC1PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_2: + TIM_OC2PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_3: + TIM_OC3PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + case TIM_Channel_4: + TIM_OC4PolarityConfig(chan->timer, TIM_OCPolarity_High); + break; + } + } + } + if (mode != PIOS_SERVO_BANK_MODE_PWM) { + // TIM_UpdateDisableConfig(pios_servo_bank_timer[bank], ENABLE); + } else { + // TIM_UpdateDisableConfig(pios_servo_bank_timer[bank], DISABLE); + } + // Setup the timer accordingly + TIM_SelectOnePulseMode(pios_servo_bank_timer[bank], TIM_OPMode_Repetitive); + TIM_Cmd(pios_servo_bank_timer[bank], ENABLE); + } +} + + +void PIOS_Servo_Update() +{ + for (uint8_t i = 0; (i < PIOS_SERVO_BANKS); i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer && pios_servo_bank_mode[i] == PIOS_SERVO_BANK_MODE_SINGLE_PULSE) { + // a pulse to be generated is longer than cycle period. skip this update. + if (TIM_GetCounter((TIM_TypeDef *)timer) > (uint32_t)(pios_servo_bank_next_update[i] + PIOS_SERVO_SAFE_MARGIN)) { + TIM_GenerateEvent((TIM_TypeDef *)timer, TIM_EventSource_Update); + pios_servo_bank_next_update[i] = pios_servo_bank_max_pulse[i]; + } + } + pios_servo_bank_max_pulse[i] = 0; + } + for (uint8_t i = 0; (i < servo_cfg->num_channels); i++) { + uint8_t bank = pios_servo_pin_bank[i]; + uint8_t mode = pios_servo_bank_mode[bank]; + if (mode == PIOS_SERVO_BANK_MODE_SINGLE_PULSE) { + /* Update the position */ + const struct pios_tim_channel *chan = &servo_cfg->channels[i]; + + switch (chan->timer_chan) { + case TIM_Channel_1: + TIM_SetCompare1(chan->timer, 0); + break; + case TIM_Channel_2: + TIM_SetCompare2(chan->timer, 0); + break; + case TIM_Channel_3: + TIM_SetCompare3(chan->timer, 0); + break; + case TIM_Channel_4: + TIM_SetCompare4(chan->timer, 0); + break; + } + } + } +} /** * Set the servo update rate (Max 500Hz) * \param[in] array of rates in Hz + * \param[in] array of timer clocks in Hz * \param[in] maximum number of banks */ -void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) +void PIOS_Servo_SetHz(const uint16_t *speeds, const uint32_t *clock, uint8_t banks) { + PIOS_Assert(banks <= PIOS_SERVO_BANKS); if (!servo_cfg) { return; } @@ -99,30 +207,22 @@ void PIOS_Servo_SetHz(const uint16_t *speeds, uint8_t banks) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - // - uint8_t set = 0; - - for (uint8_t i = 0; (i < servo_cfg->num_channels) && (set < banks); i++) { - bool new = true; - const struct pios_tim_channel *chan = &servo_cfg->channels[i]; - - /* See if any previous channels use that same timer */ - for (uint8_t j = 0; (j < i) && new; j++) { - new &= chan->timer != servo_cfg->channels[j].timer; - } - - if (new) { - // Choose the correct prescaler value for the APB the timer is attached - if (chan->timer == TIM1 || chan->timer == TIM8 || chan->timer == TIM9 || chan->timer == TIM10 || chan->timer == TIM11) { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / 1000000) - 1; - } else { - TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / 1000000) - 1; + for (uint8_t i = 0; i < banks && i < PIOS_SERVO_BANKS; i++) { + const TIM_TypeDef *timer = pios_servo_bank_timer[i]; + if (timer) { + uint32_t new_clock = PIOS_SERVO_TIMER_CLOCK; + if (clock[i]) { + new_clock = clock[i]; } - - TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1); - TIM_TimeBaseInit(chan->timer, &TIM_TimeBaseStructure); - set++; + // Choose the correct prescaler value for the APB the timer is attached + if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11) { + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB2_CLOCK / new_clock) - 1; + } else { + TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_PERIPHERAL_APB1_CLOCK / new_clock) - 1; + } + TIM_TimeBaseStructure.TIM_Period = ((new_clock / speeds[i]) - 1); + TIM_TimeBaseInit((TIM_TypeDef *)timer, &TIM_TimeBaseStructure); } } } @@ -139,22 +239,42 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position) return; } + /* Update the position */ const struct pios_tim_channel *chan = &servo_cfg->channels[servo]; + uint16_t val = position; + uint16_t margin = chan->timer->ARR / 50; // Leave 2% of period as margin to prevent overlaps + if (val > (chan->timer->ARR - margin)) { + val = chan->timer->ARR - margin; + } + + uint8_t bank = pios_servo_pin_bank[servo]; + if (pios_servo_bank_max_pulse[bank] < val) { + pios_servo_bank_max_pulse[bank] = val; + } switch (chan->timer_chan) { case TIM_Channel_1: - TIM_SetCompare1(chan->timer, position); + TIM_SetCompare1(chan->timer, val); break; case TIM_Channel_2: - TIM_SetCompare2(chan->timer, position); + TIM_SetCompare2(chan->timer, val); break; case TIM_Channel_3: - TIM_SetCompare3(chan->timer, position); + TIM_SetCompare3(chan->timer, val); break; case TIM_Channel_4: - TIM_SetCompare4(chan->timer, position); + TIM_SetCompare4(chan->timer, val); break; } } +uint8_t PIOS_Servo_GetPinBank(uint8_t pin) +{ + if (pin < servo_cfg->num_channels) { + return pios_servo_pin_bank[pin]; + } else { + return 0; + } +} + #endif /* PIOS_INCLUDE_SERVO */ diff --git a/flight/targets/boards/coptercontrol/pios_board.h b/flight/targets/boards/coptercontrol/pios_board.h index 0c131518b..f3c3e34d3 100644 --- a/flight/targets/boards/coptercontrol/pios_board.h +++ b/flight/targets/boards/coptercontrol/pios_board.h @@ -251,6 +251,7 @@ extern uint32_t pios_com_hkosd_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c index 7f8cf2812..3876a28cd 100644 --- a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c +++ b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c @@ -747,11 +747,11 @@ void PIOS_Board_Init(void) } /* Set the radio configuration parameters. */ - PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, oplinkSettings.ChannelSet, is_coordinator, is_oneway, ppm_mode, ppm_only); + PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, is_coordinator, is_oneway, ppm_mode, ppm_only); PIOS_RFM22B_SetCoordinatorID(pios_rfm22b_id, oplinkSettings.CoordID); /* Set the PPM callback if we should be receiving PPM. */ - if (ppm_mode) { + if (ppm_mode || (ppm_only && !is_coordinator)) { PIOS_RFM22B_SetPPMCallback(pios_rfm22b_id, PIOS_Board_PPM_callback); } diff --git a/flight/targets/boards/discoveryf4bare/pios_board.h b/flight/targets/boards/discoveryf4bare/pios_board.h index 0a7b0e50b..82e8df8f9 100644 --- a/flight/targets/boards/discoveryf4bare/pios_board.h +++ b/flight/targets/boards/discoveryf4bare/pios_board.h @@ -248,6 +248,7 @@ extern uint32_t pios_packet_handler; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/flight/targets/boards/oplinkmini/firmware/Makefile b/flight/targets/boards/oplinkmini/firmware/Makefile index 207de46e1..7c77ae0d8 100644 --- a/flight/targets/boards/oplinkmini/firmware/Makefile +++ b/flight/targets/boards/oplinkmini/firmware/Makefile @@ -48,6 +48,9 @@ ifndef TESTAPP SRC += $(OPUAVOBJ)/uavobjectpersistence.c SRC += $(OPUAVOBJ)/eventdispatcher.c + ## Misc library functions + SRC += $(FLIGHTLIB)/sha1.c + ## UAVObjects SRC += $(OPUAVSYNTHDIR)/oplinkstatus.c SRC += $(OPUAVSYNTHDIR)/oplinksettings.c diff --git a/flight/targets/boards/oplinkmini/firmware/pios_board.c b/flight/targets/boards/oplinkmini/firmware/pios_board.c index 44c981f45..34d033db3 100644 --- a/flight/targets/boards/oplinkmini/firmware/pios_board.c +++ b/flight/targets/boards/oplinkmini/firmware/pios_board.c @@ -438,11 +438,11 @@ void PIOS_Board_Init(void) } // Set the radio configuration parameters. - PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, oplinkSettings.ChannelSet, is_coordinator, is_oneway, ppm_mode, ppm_only); PIOS_RFM22B_SetCoordinatorID(pios_rfm22b_id, oplinkSettings.CoordID); + PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, is_coordinator, is_oneway, ppm_mode, ppm_only); /* Set the PPM callback if we should be receiving PPM. */ - if (ppm_mode) { + if (ppm_mode || (ppm_only && !is_coordinator)) { PIOS_RFM22B_SetPPMCallback(pios_rfm22b_id, PIOS_Board_PPM_callback); } diff --git a/flight/targets/boards/oplinkmini/pios_board.h b/flight/targets/boards/oplinkmini/pios_board.h index 4a976fc3e..b571a87d4 100644 --- a/flight/targets/boards/oplinkmini/pios_board.h +++ b/flight/targets/boards/oplinkmini/pios_board.h @@ -260,6 +260,7 @@ extern uint32_t pios_ppm_out_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/flight/targets/boards/osd/pios_board.h b/flight/targets/boards/osd/pios_board.h index 9b88a5e3b..f0068f978 100644 --- a/flight/targets/boards/osd/pios_board.h +++ b/flight/targets/boards/osd/pios_board.h @@ -247,6 +247,8 @@ extern uint32_t pios_com_telem_usb_id; // -------------------------- #define PIOS_TIM_MAX_DEVS 6 +#define PIOS_SERVO_BANKS 6 + // ------------------------- // USB // ------------------------- diff --git a/flight/targets/boards/revolution/firmware/Makefile b/flight/targets/boards/revolution/firmware/Makefile index 41f19521b..ae21d38ab 100644 --- a/flight/targets/boards/revolution/firmware/Makefile +++ b/flight/targets/boards/revolution/firmware/Makefile @@ -91,6 +91,7 @@ ifndef TESTAPP SRC += $(FLIGHTLIB)/insgps13state.c SRC += $(FLIGHTLIB)/auxmagsupport.c SRC += $(FLIGHTLIB)/lednotification.c + SRC += $(FLIGHTLIB)/sha1.c ## UAVObjects include ./UAVObjects.inc diff --git a/flight/targets/boards/revolution/firmware/pios_board.c b/flight/targets/boards/revolution/firmware/pios_board.c index 10893c3b8..84877b342 100644 --- a/flight/targets/boards/revolution/firmware/pios_board.c +++ b/flight/targets/boards/revolution/firmware/pios_board.c @@ -770,11 +770,11 @@ void PIOS_Board_Init(void) } /* Set the radio configuration parameters. */ - PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, oplinkSettings.ChannelSet, is_coordinator, is_oneway, ppm_mode, ppm_only); PIOS_RFM22B_SetCoordinatorID(pios_rfm22b_id, oplinkSettings.CoordID); + PIOS_RFM22B_SetChannelConfig(pios_rfm22b_id, datarate, oplinkSettings.MinChannel, oplinkSettings.MaxChannel, is_coordinator, is_oneway, ppm_mode, ppm_only); /* Set the PPM callback if we should be receiving PPM. */ - if (ppm_mode) { + if (ppm_mode || (ppm_only && !is_coordinator)) { PIOS_RFM22B_SetPPMCallback(pios_rfm22b_id, PIOS_Board_PPM_callback); } diff --git a/flight/targets/boards/revolution/pios_board.h b/flight/targets/boards/revolution/pios_board.h index 09a2be105..7f9ab9d77 100644 --- a/flight/targets/boards/revolution/pios_board.h +++ b/flight/targets/boards/revolution/pios_board.h @@ -268,7 +268,7 @@ extern uint32_t pios_packet_handler; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ - +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings // -------------------------- diff --git a/flight/targets/boards/revoproto/pios_board.h b/flight/targets/boards/revoproto/pios_board.h index 6da2bbd9c..d3a421114 100644 --- a/flight/targets/boards/revoproto/pios_board.h +++ b/flight/targets/boards/revoproto/pios_board.h @@ -225,6 +225,7 @@ extern uint32_t pios_com_hkosd_id; // ------------------------- #define PIOS_SERVO_UPDATE_HZ 50 #define PIOS_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */ +#define PIOS_SERVO_BANKS 6 // -------------------------- // Timer controller settings diff --git a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml index 031abd755..17c8c46a5 100644 --- a/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml +++ b/ground/openpilotgcs/share/openpilotgcs/default_configurations/OpenPilotGCS.xml @@ -1551,6 +1551,17 @@ false + + + false + 0.0.0 + + + %%DATAPATH%%models/multi/blackout/BlackoutMiniHQuad.3DS + %%DATAPATH%%models/backgrounds/default_background.png + false + + false @@ -2530,7 +2541,7 @@ ModelViewGadget - Test Quad X + Blackout_MiniH uavGadget diff --git a/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.3DS b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.3DS new file mode 100755 index 000000000..1217e54de Binary files /dev/null and b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.3DS differ diff --git a/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.jpg b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.jpg new file mode 100755 index 000000000..de2db9dcb Binary files /dev/null and b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/BlackoutMiniHQuad.jpg differ diff --git a/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/TEXTURE.PNG b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/TEXTURE.PNG new file mode 100755 index 000000000..3c430b5df Binary files /dev/null and b/ground/openpilotgcs/share/openpilotgcs/models/multi/blackout/TEXTURE.PNG differ diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp index b7b9c634c..ee28e2501 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.cpp @@ -100,40 +100,40 @@ void OPMapWidget::SetUavPic(QString UAVPic) } } -WayPointLine *OPMapWidget::WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color) +WayPointLine *OPMapWidget::WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color, bool dashed, int width) { if (!from | !to) { return NULL; } - WayPointLine *ret = new WayPointLine(from, to, map, color); + WayPointLine *ret = new WayPointLine(from, to, map, color, dashed, width); ret->setOpacity(overlayOpacity); return ret; } -WayPointLine *OPMapWidget::WPLineCreate(HomeItem *from, WayPointItem *to, QColor color) +WayPointLine *OPMapWidget::WPLineCreate(HomeItem *from, WayPointItem *to, QColor color, bool dashed, int width) { if (!from | !to) { return NULL; } - WayPointLine *ret = new WayPointLine(from, to, map, color); + WayPointLine *ret = new WayPointLine(from, to, map, color, dashed, width); ret->setOpacity(overlayOpacity); return ret; } -WayPointCircle *OPMapWidget::WPCircleCreate(WayPointItem *center, WayPointItem *radius, bool clockwise, QColor color) +WayPointCircle *OPMapWidget::WPCircleCreate(WayPointItem *center, WayPointItem *radius, bool clockwise, QColor color, bool dashed, int width) { if (!center | !radius) { return NULL; } - WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color); + WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color, dashed, width); ret->setOpacity(overlayOpacity); return ret; } -WayPointCircle *OPMapWidget::WPCircleCreate(HomeItem *center, WayPointItem *radius, bool clockwise, QColor color) +WayPointCircle *OPMapWidget::WPCircleCreate(HomeItem *center, WayPointItem *radius, bool clockwise, QColor color, bool dashed, int width) { if (!center | !radius) { return NULL; } - WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color); + WayPointCircle *ret = new WayPointCircle(center, radius, clockwise, map, color, dashed, width); ret->setOpacity(overlayOpacity); return ret; } diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.h index 51700eab5..005509908 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/opmapwidget.h @@ -511,10 +511,10 @@ public: } void SetShowDiagnostics(bool const & value); void SetUavPic(QString UAVPic); - WayPointLine *WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color); - WayPointLine *WPLineCreate(HomeItem *from, WayPointItem *to, QColor color); - WayPointCircle *WPCircleCreate(WayPointItem *center, WayPointItem *radius, bool clockwise, QColor color); - WayPointCircle *WPCircleCreate(HomeItem *center, WayPointItem *radius, bool clockwise, QColor color); + WayPointLine *WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color, bool dashed = false, int width = -1); + WayPointLine *WPLineCreate(HomeItem *from, WayPointItem *to, QColor color, bool dashed = false, int width = -1); + WayPointCircle *WPCircleCreate(WayPointItem *center, WayPointItem *radius, bool clockwise, QColor color, bool dashed = false, int width = -1); + WayPointCircle *WPCircleCreate(HomeItem *center, WayPointItem *radius, bool clockwise, QColor color, bool dashed = false, int width = -1); void deleteAllOverlays(); void WPSetVisibleAll(bool value); WayPointItem *magicWPCreate(); diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.cpp index 9cf9cc89e..ff3216c3e 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.cpp @@ -29,8 +29,8 @@ #include "homeitem.h" namespace mapcontrol { -WayPointCircle::WayPointCircle(WayPointItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color) : QGraphicsEllipseItem(map), - my_center(center), my_radius(radius), my_map(map), myColor(color), myClockWise(clockwise) +WayPointCircle::WayPointCircle(WayPointItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color, bool dashed, int width) : QGraphicsEllipseItem(map), + my_center(center), my_radius(radius), my_map(map), myColor(color), myClockWise(clockwise), dashed(dashed), width(width) { connect(center, SIGNAL(localPositionChanged(QPointF, WayPointItem *)), this, SLOT(refreshLocations())); connect(radius, SIGNAL(localPositionChanged(QPointF, WayPointItem *)), this, SLOT(refreshLocations())); @@ -40,8 +40,8 @@ WayPointCircle::WayPointCircle(WayPointItem *center, WayPointItem *radius, bool connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); } -WayPointCircle::WayPointCircle(HomeItem *radius, WayPointItem *center, bool clockwise, MapGraphicItem *map, QColor color) : QGraphicsEllipseItem(map), - my_center(center), my_radius(radius), my_map(map), myColor(color), myClockWise(clockwise) +WayPointCircle::WayPointCircle(HomeItem *radius, WayPointItem *center, bool clockwise, MapGraphicItem *map, QColor color, bool dashed, int width) : QGraphicsEllipseItem(map), + my_center(center), my_radius(radius), my_map(map), myColor(color), myClockWise(clockwise), dashed(dashed), width(width) { connect(radius, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(refreshLocations())); connect(center, SIGNAL(localPositionChanged(QPointF)), this, SLOT(refreshLocations())); @@ -67,6 +67,14 @@ void WayPointCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *op p2 = QPointF(line.p1().x(), line.p1().y() - line.length()); QPen myPen = pen(); myPen.setColor(myColor); + if (width > 0) { + myPen.setWidth(width); + } + if (dashed) { + QVector dashes; + dashes << 4 << 8; + myPen.setDashPattern(dashes); + } qreal arrowSize = 10; painter->setPen(myPen); QBrush brush = painter->brush(); diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.h index ec6ac5a13..43bc99a8b 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointcircle.h @@ -40,8 +40,8 @@ class WayPointCircle : public QObject, public QGraphicsEllipseItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: enum { Type = UserType + 9 }; - WayPointCircle(WayPointItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color = Qt::green); - WayPointCircle(HomeItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color = Qt::green); + WayPointCircle(WayPointItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color = Qt::green, bool dashed = false, int width = -1); + WayPointCircle(HomeItem *center, WayPointItem *radius, bool clockwise, MapGraphicItem *map, QColor color = Qt::green, bool dashed = false, int width = -1); int type() const; void setColor(const QColor &color) { @@ -55,6 +55,8 @@ private: QColor myColor; bool myClockWise; QLineF line; + bool dashed; + int width; protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); public slots: diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.cpp index 62e595784..02f8522a0 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.cpp @@ -29,8 +29,8 @@ #include "homeitem.h" namespace mapcontrol { -WayPointLine::WayPointLine(WayPointItem *from, WayPointItem *to, MapGraphicItem *map, QColor color) : QGraphicsLineItem(map), - source(from), destination(to), my_map(map), myColor(color) +WayPointLine::WayPointLine(WayPointItem *from, WayPointItem *to, MapGraphicItem *map, QColor color, bool dashed, int width) : QGraphicsLineItem(map), + source(from), destination(to), my_map(map), myColor(color), dashed(dashed), lineWidth(width) { this->setLine(to->pos().x(), to->pos().y(), from->pos().x(), from->pos().y()); connect(from, SIGNAL(localPositionChanged(QPointF, WayPointItem *)), this, SLOT(refreshLocations())); @@ -47,8 +47,8 @@ WayPointLine::WayPointLine(WayPointItem *from, WayPointItem *to, MapGraphicItem connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal))); } -WayPointLine::WayPointLine(HomeItem *from, WayPointItem *to, MapGraphicItem *map, QColor color) : QGraphicsLineItem(map), - source(from), destination(to), my_map(map), myColor(color) +WayPointLine::WayPointLine(HomeItem *from, WayPointItem *to, MapGraphicItem *map, QColor color, bool dashed, int width) : QGraphicsLineItem(map), + source(from), destination(to), my_map(map), myColor(color), dashed(dashed), lineWidth(width) { this->setLine(to->pos().x(), to->pos().y(), from->pos().x(), from->pos().y()); connect(from, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(refreshLocations())); @@ -98,12 +98,23 @@ void WayPointLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti arrowHead.clear(); arrowHead << line().pointAt(0.5) << arrowP1 << arrowP2; painter->drawPolygon(arrowHead); - if (myColor == Qt::red) { - myPen.setWidth(3); - } else if (myColor == Qt::yellow) { - myPen.setWidth(2); - } else if (myColor == Qt::green) { - myPen.setWidth(1); + + if (dashed) { + QVector dashes; + dashes << 4 << 8; + myPen.setDashPattern(dashes); + } + + if (lineWidth == -1) { + if (myColor == Qt::red) { + myPen.setWidth(3); + } else if (myColor == Qt::yellow) { + myPen.setWidth(2); + } else if (myColor == Qt::green) { + myPen.setWidth(1); + } + } else { + myPen.setWidth(lineWidth); } painter->setPen(myPen); painter->drawLine(line()); diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.h index cc1cc3b93..ed1ea81d2 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/mapwidget/waypointline.h @@ -40,8 +40,8 @@ class WayPointLine : public QObject, public QGraphicsLineItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: enum { Type = UserType + 8 }; - WayPointLine(WayPointItem *from, WayPointItem *to, MapGraphicItem *map, QColor color = Qt::green); - WayPointLine(HomeItem *from, WayPointItem *to, MapGraphicItem *map, QColor color = Qt::green); + WayPointLine(WayPointItem *from, WayPointItem *to, MapGraphicItem *map, QColor color = Qt::green, bool dashed = false, int width = -1); + WayPointLine(HomeItem *from, WayPointItem *to, MapGraphicItem *map, QColor color = Qt::green, bool dashed = false, int width = -1); int type() const; QPainterPath shape() const; void setColor(const QColor &color) @@ -54,6 +54,8 @@ private: MapGraphicItem *my_map; QPolygonF arrowHead; QColor myColor; + bool dashed; + int lineWidth; protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); public slots: diff --git a/ground/openpilotgcs/src/plugins/config/airframe_multirotor.ui b/ground/openpilotgcs/src/plugins/config/airframe_multirotor.ui index 4d96dce60..15efc09f6 100644 --- a/ground/openpilotgcs/src/plugins/config/airframe_multirotor.ui +++ b/ground/openpilotgcs/src/plugins/config/airframe_multirotor.ui @@ -511,7 +511,7 @@ Typical value is 50% for + or X configuration on quads. Motor output channels - + 9 @@ -524,61 +524,41 @@ Typical value is 50% for + or X configuration on quads. 9 - - + + QLayout::SetMaximumSize - - QFormLayout::AllNonFixedFieldsGrow + + 0 - - 6 - - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - 1 - - - - - - - Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. - - - - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - 2 - - - - + + + + 0 + 0 + + + + + 0 + 0 + + - Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + Select output channel for Accessory0 RcInput - + + + + 90 + 0 + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); @@ -587,19 +567,30 @@ font: bold 12px; margin:1px; - 3 + Accessory1 + + + Qt::AlignCenter - - + + + + + 0 + 0 + + + + + 120 + 0 + + - Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + RcOutput channels - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); @@ -608,19 +599,204 @@ font: bold 12px; margin:1px; - 4 + RC Output + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Accessory0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 90 + 16 + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + RC Input + + + Qt::AlignCenter - + + + + 0 + 0 + + + + + 0 + 0 + + - Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + Select output channel for Accessory2 RcInput + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Select output channel for Accessory1 RcInput + + + + + + + + 90 + 0 + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Accessory2 + + + Qt::AlignCenter + + + + + + + RcOutput curve + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Curve + + + Qt::AlignCenter + + + + + + + Select output curve for Accessory0 RcInput + + + + + + + Select output curve for Accessory1 RcInput + + + + + + + Select output curve for Accessory2 RcInput + + + + + 0 + 0 + + + + + 0 + 16 + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Tricopter Yaw Servo channel + + + Qt::AlignCenter + + + @@ -749,7 +925,143 @@ margin:1px; - + + + + true + + + + 0 + 0 + + + + + 40 + 20 + + + + + + + + QLayout::SetMaximumSize + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + 1 + + + + + + + Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + + + + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + 2 + + + + + + + Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + + + + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + 3 + + + + + + + Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + + + + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + 4 + + + + + + + Assign your motor output channels using the drawing above as a reference. Respect propeller rotation. + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 20 + + + + Reverse all motors + + + + @@ -778,61 +1090,6 @@ margin:1px; - - - - true - - - - 0 - 0 - - - - - 40 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 16 - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Tricopter Yaw Servo channel - - - Qt::AlignCenter - - - - - - - Reverse all motors - - - diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp index e186a5972..6681a5b17 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.cpp @@ -110,6 +110,17 @@ QStringList ConfigMultiRotorWidget::getChannelDescriptions() if (multi.TRIYaw > 0 && multi.TRIYaw <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) { channelDesc[multi.TRIYaw - 1] = QString("Tri-Yaw"); } + + if (multi.Accessory0 > 0 && multi.Accessory0 <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) { + channelDesc[multi.Accessory0 - 1] = QString("Accessory0"); + } + if (multi.Accessory1 > 0 && multi.Accessory1 <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) { + channelDesc[multi.Accessory1 - 1] = QString("Accessory1"); + } + if (multi.Accessory2 > 0 && multi.Accessory2 <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) { + channelDesc[multi.Accessory2 - 1] = QString("Accessory2"); + } + return channelDesc; } @@ -120,6 +131,12 @@ ConfigMultiRotorWidget::ConfigMultiRotorWidget(QWidget *parent) : populateChannelComboBoxes(); + QStringList mixerCurveList; + mixerCurveList << "Curve1" << "Curve2"; + m_aircraft->rcOutputCurveBox1->addItems(mixerCurveList); + m_aircraft->rcOutputCurveBox2->addItems(mixerCurveList); + m_aircraft->rcOutputCurveBox3->addItems(mixerCurveList); + // Setup the Multirotor picture in the Quad settings interface m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -151,6 +168,7 @@ ConfigMultiRotorWidget::ConfigMultiRotorWidget(QWidget *parent) : m_aircraft->multiThrottleCurve->setXAxisLabel(tr("Input")); m_aircraft->multiThrottleCurve->setYAxisLabel(tr("Output")); + updateEnableControls(); } @@ -319,6 +337,12 @@ void ConfigMultiRotorWidget::registerWidgets(ConfigTaskWidget &parent) parent.addWidget(m_aircraft->mrYawMixLevel); parent.addWidget(m_aircraft->triYawChannelBox); parent.addWidget(m_aircraft->MultirotorRevMixerCheckBox); + parent.addWidget(m_aircraft->rcOutputChannelBox1); + parent.addWidget(m_aircraft->rcOutputChannelBox2); + parent.addWidget(m_aircraft->rcOutputChannelBox3); + parent.addWidget(m_aircraft->rcOutputCurveBox1); + parent.addWidget(m_aircraft->rcOutputCurveBox2); + parent.addWidget(m_aircraft->rcOutputCurveBox3); } void ConfigMultiRotorWidget::resetActuators(GUIConfigDataUnion *configData) @@ -342,6 +366,46 @@ void ConfigMultiRotorWidget::resetActuators(GUIConfigDataUnion *configData) configData->multi.VTOLMotorNNW = 0; } +void ConfigMultiRotorWidget::resetRcOutputs(GUIConfigDataUnion *configData) +{ + configData->multi.Accessory0 = 0; + configData->multi.Accessory1 = 0; + configData->multi.Accessory2 = 0; +} + +void ConfigMultiRotorWidget::resetMixers() +{ + UAVDataObject *mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + + Q_ASSERT(mixer); + + for (int channel = 0; channel < (int)ConfigMultiRotorWidget::CHANNEL_NUMELEM; channel++) { + resetMixerVector(mixer, channel); + } +} + +void ConfigMultiRotorWidget::updateRcCurvesUsed() +{ + UAVDataObject *mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + + Q_ASSERT(mixer); + + setComboCurrentIndex(m_aircraft->rcOutputCurveBox1, VehicleConfig::MIXER_THROTTLECURVE1); + setComboCurrentIndex(m_aircraft->rcOutputCurveBox2, VehicleConfig::MIXER_THROTTLECURVE1); + setComboCurrentIndex(m_aircraft->rcOutputCurveBox3, VehicleConfig::MIXER_THROTTLECURVE1); + + for (int channel = 0; channel < (int)ConfigMultiRotorWidget::CHANNEL_NUMELEM; channel++) { + QString mixerType = getMixerType(mixer, channel); + if (mixerType == "Accessory0" && getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2)) { + setComboCurrentIndex(m_aircraft->rcOutputCurveBox1, VehicleConfig::MIXER_THROTTLECURVE2); + } else if (mixerType == "Accessory1" && getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2)) { + setComboCurrentIndex(m_aircraft->rcOutputCurveBox2, VehicleConfig::MIXER_THROTTLECURVE2); + } else if (mixerType == "Accessory2" && getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2)) { + setComboCurrentIndex(m_aircraft->rcOutputCurveBox3, VehicleConfig::MIXER_THROTTLECURVE2); + } + } +} + /** Helper function to refresh the UI widget values */ @@ -457,6 +521,12 @@ void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType) setComboCurrentIndex(m_aircraft->triYawChannelBox, multi.TRIYaw); } + setComboCurrentIndex(m_aircraft->rcOutputChannelBox1, multi.Accessory0); + setComboCurrentIndex(m_aircraft->rcOutputChannelBox2, multi.Accessory1); + setComboCurrentIndex(m_aircraft->rcOutputChannelBox3, multi.Accessory2); + + updateRcCurvesUsed(); + // Now, read mixing values stored on board and applies values on sliders. m_aircraft->mrPitchMixLevel->setValue(getMixerValue(mixer, "MixerValuePitch")); m_aircraft->mrRollMixLevel->setValue(getMixerValue(mixer, "MixerValueRoll")); @@ -476,6 +546,13 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() Q_ASSERT(mixer); + // Reset all Mixers + resetMixers(); + + QList rcOutputList; + rcOutputList << "Accessory0" << "Accessory1" << "Accessory2"; + setupRcOutputs(rcOutputList); + // Curve is also common to all quads: setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve()); @@ -731,7 +808,6 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() m_aircraft->mrStatusLabel->setText(tr("Configuration OK")); } - return airframeType; } @@ -816,6 +892,62 @@ void ConfigMultiRotorWidget::setupQuadMotor(int channel, double pitch, double ro setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, yaw * 127); } +/** + Helper function: setup rc outputs. Takes a list of channel names in input. + */ +void ConfigMultiRotorWidget::setupRcOutputs(QList rcOutputList) +{ + QList rcList; + rcList << m_aircraft->rcOutputChannelBox1 << m_aircraft->rcOutputChannelBox2 << m_aircraft->rcOutputChannelBox3; + + GUIConfigDataUnion configData = getConfigData(); + resetRcOutputs(&configData); + + UAVDataObject *mixer = dynamic_cast(getObjectManager()->getObject(QString("MixerSettings"))); + Q_ASSERT(mixer); + + int curveAccessory0 = m_aircraft->rcOutputCurveBox1->currentIndex(); + int curveAccessory1 = m_aircraft->rcOutputCurveBox2->currentIndex(); + int curveAccessory2 = m_aircraft->rcOutputCurveBox3->currentIndex(); + + foreach(QString rc_output, rcOutputList) { + int index = rcList.takeFirst()->currentIndex(); + + if (rc_output == QString("Accessory0")) { + configData.multi.Accessory0 = index; + if (index) { + setMixerType(mixer, index - 1, VehicleConfig::MIXERTYPE_ACCESSORY0); + if (curveAccessory0) { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); + } else { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); + } + } + } else if (rc_output == QString("Accessory1")) { + configData.multi.Accessory1 = index; + if (index) { + setMixerType(mixer, index - 1, VehicleConfig::MIXERTYPE_ACCESSORY1); + if (curveAccessory1) { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); + } else { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); + } + } + } else if (rc_output == QString("Accessory2")) { + configData.multi.Accessory2 = index; + if (index) { + setMixerType(mixer, index - 1, VehicleConfig::MIXERTYPE_ACCESSORY2); + if (curveAccessory2) { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); + } else { + setMixerVectorValue(mixer, index - 1, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); + } + } + } + } + setConfigData(configData); +} + /** Helper function: setup motors. Takes a list of channel names in input. */ @@ -1052,10 +1184,11 @@ bool ConfigMultiRotorWidget::throwConfigError(int numMotors) { // Initialize configuration error flag bool error = false; + QString channelNames = ""; // Iterate through all instances of multiMotorChannelBox for (int i = 0; i < numMotors; i++) { - // Fine widgets with text "multiMotorChannelBox.x", where x is an integer + // Find widgets with his name "multiMotorChannelBox.x", where x is an integer QComboBox *combobox = this->findChild("multiMotorChannelBox" + QString::number(i + 1)); if (combobox) { if (combobox->currentText() == "None") { @@ -1064,9 +1197,40 @@ bool ConfigMultiRotorWidget::throwConfigError(int numMotors) pixmap.fill(QColor("red")); combobox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes error = true; + } else if (channelNames.contains(combobox->currentText(), Qt::CaseInsensitive)) { + int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize); + QPixmap pixmap(size, size); + pixmap.fill(QColor("orange")); + combobox->setItemData(combobox->currentIndex(), pixmap, Qt::DecorationRole); // Set color palettes + combobox->setToolTip(tr("Duplicate channel in motor outputs")); } else { - combobox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes + for (int index = 0; index < (int)ConfigMultiRotorWidget::CHANNEL_NUMELEM; index++) { + combobox->setItemData(index, 0, Qt::DecorationRole); // Reset all color palettes + combobox->setToolTip(""); + } } + channelNames += (combobox->currentText() == "None") ? "" : combobox->currentText(); + } + } + + // Iterate through all instances of rcOutputChannelBox + for (int i = 0; i < 3; i++) { + // Find widgets with his name "rcOutputChannelBox.x", where x is an integer + QComboBox *combobox = this->findChild("rcOutputChannelBox" + QString::number(i + 1)); + if (combobox) { + if (channelNames.contains(combobox->currentText(), Qt::CaseInsensitive)) { + int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize); + QPixmap pixmap(size, size); + pixmap.fill(QColor("orange")); + combobox->setItemData(combobox->currentIndex(), pixmap, Qt::DecorationRole); // Set color palettes + combobox->setToolTip(tr("Channel already used")); + } else { + for (int index = 0; index < (int)ConfigMultiRotorWidget::CHANNEL_NUMELEM; index++) { + combobox->setItemData(index, 0, Qt::DecorationRole); // Reset all color palettes + combobox->setToolTip(tr("Select output channel for Accessory%1 RcInput").arg(i)); + } + } + channelNames += (combobox->currentText() == "None") ? "" : combobox->currentText(); } } diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h index dde2ced06..488fd5cce 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/configmultirotorwidget.h @@ -65,16 +65,19 @@ private: virtual void registerWidgets(ConfigTaskWidget &parent); virtual void resetActuators(GUIConfigDataUnion *configData); + virtual void resetRcOutputs(GUIConfigDataUnion *configData); bool setupQuad(bool pLayout); bool setupHexa(bool pLayout); bool setupOcto(); bool setupMultiRotorMixer(double mixerFactors[8][3]); void setupMotors(QList motorList); + void setupRcOutputs(QList rcOutputList); + void resetMixers(); void setupQuadMotor(int channel, double roll, double pitch, double yaw); void setYawMixLevel(int); - + void updateRcCurvesUsed(); void updateAirframe(QString multiRotorType); void setupEnabledControls(QString multiRotorType); diff --git a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h index 6dfe1760a..0a27e8390 100644 --- a/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h +++ b/ground/openpilotgcs/src/plugins/config/cfg_vehicletypes/vehicleconfig.h @@ -52,7 +52,10 @@ typedef struct { uint VTOLMotorWNW : 4; uint VTOLMotorNNW : 4; // 64 bits uint TRIYaw : 4; - quint32 padding : 28; // 96 bits + uint Accessory0 : 4; + uint Accessory1 : 4; + uint Accessory2 : 4; + quint32 padding : 16; // 96 bits quint32 padding1; // 128 bits } __attribute__((packed)) multiGUISettingsStruct; diff --git a/ground/openpilotgcs/src/plugins/config/config.pro b/ground/openpilotgcs/src/plugins/config/config.pro index cea1b866d..f6e816e3d 100644 --- a/ground/openpilotgcs/src/plugins/config/config.pro +++ b/ground/openpilotgcs/src/plugins/config/config.pro @@ -23,7 +23,6 @@ HEADERS += \ configvehicletypewidget.h \ config_cc_hw_widget.h \ configccattitudewidget.h \ - configpipxtremewidget.h \ configstabilizationwidget.h \ assertions.h \ defaultattitudewidget.h \ @@ -57,7 +56,8 @@ HEADERS += \ calibration/sixpointcalibrationmodel.h \ calibration/levelcalibrationmodel.h \ calibration/gyrobiascalibrationmodel.h \ - calibration/calibrationuiutils.h + calibration/calibrationuiutils.h \ + configoplinkwidget.h SOURCES += \ configplugin.cpp \ @@ -71,7 +71,6 @@ SOURCES += \ config_cc_hw_widget.cpp \ configccattitudewidget.cpp \ configstabilizationwidget.cpp \ - configpipxtremewidget.cpp \ defaultattitudewidget.cpp \ defaulthwsettingswidget.cpp \ channelform.cpp \ @@ -97,7 +96,8 @@ SOURCES += \ calibration/thermal/thermalcalibrationmodel.cpp \ calibration/sixpointcalibrationmodel.cpp \ calibration/levelcalibrationmodel.cpp \ - calibration/gyrobiascalibrationmodel.cpp + calibration/gyrobiascalibrationmodel.cpp \ + configoplinkwidget.cpp FORMS += \ airframe.ui \ @@ -118,8 +118,8 @@ FORMS += \ outputchannelform.ui \ revosensors.ui \ txpid.ui \ - pipxtreme.ui \ mixercurve.ui \ - configrevohwwidget.ui + configrevohwwidget.ui \ + oplink.ui RESOURCES += configgadget.qrc diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index cd359019b..a611c6c51 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -36,7 +36,7 @@ #include "configtxpidwidget.h" #include "configrevohwwidget.h" #include "config_cc_hw_widget.h" -#include "configpipxtremewidget.h" +#include "configoplinkwidget.h" #include "configrevowidget.h" #include "defaultattitudewidget.h" #include "defaulthwsettingswidget.h" @@ -240,7 +240,7 @@ void ConfigGadgetWidget::updateOPLinkStatus(UAVObject *) icon->addFile(":/configgadget/images/pipx-normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/pipx-selected.png", QSize(), QIcon::Selected, QIcon::Off); - QWidget *qwd = new ConfigPipXtremeWidget(this); + QWidget *qwd = new ConfigOPLinkWidget(this); stackWidget->insertTab(ConfigGadgetWidget::oplink, qwd, *icon, QString("OPLink")); oplinkConnected = true; } diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index e6256cf98..f43d63eb2 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -544,22 +544,9 @@ void ConfigInputWidget::wzNext() // Load actuator settings back from beginning of wizard actuatorSettingsObj->setData(previousActuatorSettingsData); - // Leave setting the throttle neutral until the final Next press, - // else the throttle scaling causes the graphical stick movement to not - // match the tx stick - manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE] = - manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE] + - ((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE] - - manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]) * 0.04); - if ((abs(manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE] - - manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE]) < 100) || - (abs(manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE] - - manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE]) < 100)) { - manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE] = - manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE] + - (manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE] - - manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]) / 2; - } + // Force flight mode neutral to middle and Throttle neutral at 4% + adjustSpecialNeutrals(); + manualSettingsObj->setData(manualSettingsData); // move to Arming Settings tab ui->stackedWidget->setCurrentIndex(0); @@ -1595,7 +1582,7 @@ void ConfigInputWidget::updateCalibration() (reverse[i] && manualSettingsData.ChannelMax[i] > manualCommandData.Channel[i])) { manualSettingsData.ChannelMax[i] = manualCommandData.Channel[i]; } - if (i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE || i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE) { + if ((i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE) || (i == ManualControlSettings::CHANNELNUMBER_THROTTLE)) { adjustSpecialNeutrals(); } else { manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i]; @@ -1659,7 +1646,7 @@ void ConfigInputWidget::simpleCalibration(bool enable) restoreMdataSingle(manualCommandObj, &manualControlMdata); for (unsigned int i = 0; i < ManualControlCommand::CHANNEL_NUMELEM; i++) { - if (i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE || i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE) { + if ((i == ManualControlSettings::CHANNELNUMBER_FLIGHTMODE) || (i == ManualControlSettings::CHANNELNUMBER_THROTTLE)) { adjustSpecialNeutrals(); } else { manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i]; @@ -1680,9 +1667,9 @@ void ConfigInputWidget::adjustSpecialNeutrals() // FlightMode and Throttle need special neutral settings // // Force flight mode neutral to middle - manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE] = - (manualSettingsData.ChannelMax[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE] + - manualSettingsData.ChannelMin[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE]) / 2; + manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE] = + (manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE] + + manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]) / 2; // Force throttle to be near min, add 4% from total range to avoid arming issues manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE] = diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp b/ground/openpilotgcs/src/plugins/config/configoplinkwidget.cpp similarity index 95% rename from ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp rename to ground/openpilotgcs/src/plugins/config/configoplinkwidget.cpp index 684f32b78..56a42658e 100644 --- a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoplinkwidget.cpp @@ -25,7 +25,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "configpipxtremewidget.h" +#include "configoplinkwidget.h" #include #include @@ -38,7 +38,7 @@ static const int MIN_CHANNEL_RANGE = 10; static const float FIRST_FREQUENCY = 430.000; static const float FREQUENCY_STEP = 0.040; -ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget(parent) +ConfigOPLinkWidget::ConfigOPLinkWidget(QWidget *parent) : ConfigTaskWidget(parent) { m_oplink = new Ui_OPLinkWidget(); m_oplink->setupUi(this); @@ -67,7 +67,6 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget addWidgetBinding("OPLinkSettings", "MaxRFPower", m_oplink->MaxRFTxPower); addWidgetBinding("OPLinkSettings", "MinChannel", m_oplink->MinimumChannel); addWidgetBinding("OPLinkSettings", "MaxChannel", m_oplink->MaximumChannel); - addWidgetBinding("OPLinkSettings", "ChannelSet", m_oplink->ChannelSet); addWidgetBinding("OPLinkSettings", "CoordID", m_oplink->CoordID); addWidgetBinding("OPLinkSettings", "Coordinator", m_oplink->Coordinator); addWidgetBinding("OPLinkSettings", "OneWay", m_oplink->OneWayLink); @@ -83,7 +82,6 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget addWidgetBinding("OPLinkStatus", "RxFailure", m_oplink->RxFailure); addWidgetBinding("OPLinkStatus", "UAVTalkErrors", m_oplink->UAVTalkErrors); addWidgetBinding("OPLinkStatus", "TxDropped", m_oplink->Dropped); - addWidgetBinding("OPLinkStatus", "TxResent", m_oplink->Resent); addWidgetBinding("OPLinkStatus", "TxFailure", m_oplink->TxFailure); addWidgetBinding("OPLinkStatus", "Resets", m_oplink->Resets); addWidgetBinding("OPLinkStatus", "Timeouts", m_oplink->Timeouts); @@ -119,13 +117,13 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget updateEnableControls(); } -ConfigPipXtremeWidget::~ConfigPipXtremeWidget() +ConfigOPLinkWidget::~ConfigOPLinkWidget() {} /*! \brief Called by updates to @OPLinkStatus */ -void ConfigPipXtremeWidget::updateStatus(UAVObject *object) +void ConfigOPLinkWidget::updateStatus(UAVObject *object) { // Request and update of the setting object if we haven't received it yet. if (!settingsUpdated) { @@ -233,7 +231,7 @@ void ConfigPipXtremeWidget::updateStatus(UAVObject *object) /*! \brief Called by updates to @OPLinkSettings */ -void ConfigPipXtremeWidget::updateSettings(UAVObject *object) +void ConfigOPLinkWidget::updateSettings(UAVObject *object) { Q_UNUSED(object); @@ -284,20 +282,20 @@ void ConfigPipXtremeWidget::updateSettings(UAVObject *object) } } -void ConfigPipXtremeWidget::updateEnableControls() +void ConfigOPLinkWidget::updateEnableControls() { enableControls(true); ppmOnlyChanged(); } -void ConfigPipXtremeWidget::disconnected() +void ConfigOPLinkWidget::disconnected() { if (settingsUpdated) { settingsUpdated = false; } } -void ConfigPipXtremeWidget::bind() +void ConfigOPLinkWidget::bind() { QPushButton *bindButton = qobject_cast(sender()); @@ -323,7 +321,7 @@ void ConfigPipXtremeWidget::bind() } } -void ConfigPipXtremeWidget::ppmOnlyChanged() +void ConfigOPLinkWidget::ppmOnlyChanged() { bool is_ppm_only = m_oplink->PPMOnly->isChecked(); @@ -332,17 +330,17 @@ void ConfigPipXtremeWidget::ppmOnlyChanged() m_oplink->ComSpeed->setEnabled(!is_ppm_only); } -void ConfigPipXtremeWidget::minChannelChanged() +void ConfigOPLinkWidget::minChannelChanged() { channelChanged(false); } -void ConfigPipXtremeWidget::maxChannelChanged() +void ConfigOPLinkWidget::maxChannelChanged() { channelChanged(true); } -void ConfigPipXtremeWidget::channelChanged(bool isMax) +void ConfigOPLinkWidget::channelChanged(bool isMax) { int minChannel = m_oplink->MinimumChannel->value(); int maxChannel = m_oplink->MaximumChannel->value(); diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h b/ground/openpilotgcs/src/plugins/config/configoplinkwidget.h similarity index 92% rename from ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h rename to ground/openpilotgcs/src/plugins/config/configoplinkwidget.h index bd2ebd0bf..bda71c46e 100644 --- a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoplinkwidget.h @@ -29,15 +29,15 @@ #include -#include "ui_pipxtreme.h" +#include "ui_oplink.h" #include "configtaskwidget.h" -class ConfigPipXtremeWidget : public ConfigTaskWidget { +class ConfigOPLinkWidget : public ConfigTaskWidget { Q_OBJECT public: - ConfigPipXtremeWidget(QWidget *parent = 0); - ~ConfigPipXtremeWidget(); + ConfigOPLinkWidget(QWidget *parent = 0); + ~ConfigOPLinkWidget(); public slots: void updateStatus(UAVObject *object1); diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 769c25066..330911bf4 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -98,9 +98,18 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren addWidget(ui->cb_outputRate1); addWidget(ui->spinningArmed); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode1, 0, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode2, 1, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode3, 2, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode4, 3, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode5, 4, 0, true); + addWidgetBinding("ActuatorSettings", "BankMode", ui->cb_outputMode6, 5, 0, true); + disconnect(this, SLOT(refreshWidgetsValues(UAVObject *))); + populateWidgets(); refreshWidgetsValues(); + updateEnableControls(); } @@ -240,6 +249,17 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) actuatorCommand->setData(actuatorCommandFields); } +void ConfigOutputWidget::setColor(QWidget *widget, const QColor color) +{ + QPalette p(palette()); + + p.setColor(QPalette::Background, color); + p.setColor(QPalette::Base, color); + p.setColor(QPalette::Active, QPalette::Button, color); + p.setColor(QPalette::Inactive, QPalette::Button, color); + widget->setAutoFillBackground(true); + widget->setPalette(p); +} /******************************** * Output settings @@ -250,22 +270,33 @@ void ConfigOutputWidget::sendChannelTest(int index, int value) */ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) { - Q_UNUSED(obj); - bool dirty = isDirty(); + ConfigTaskWidget::refreshWidgetsValues(obj); + // Get Actuator Settings ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager()); + Q_ASSERT(actuatorSettings); ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData(); // Get channel descriptions - QStringList ChannelDesc = ConfigVehicleTypeWidget::getChannelDescriptions(); + QStringList channelDesc = ConfigVehicleTypeWidget::getChannelDescriptions(); + + QList channelBanks; + QList bankColors; + bankColors + << QColor("#C6ECAE") + << QColor("#91E5D3") + << QColor("#FCEC52") + << QColor("#C3A8FF") + << QColor("#F7F7F2") + << QColor("#FF9F51"); // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { - outputChannelForm->setName(ChannelDesc[outputChannelForm->index()]); + outputChannelForm->setName(channelDesc[outputChannelForm->index()]); // init min,max,neutral int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; @@ -279,89 +310,78 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) // Get the SpinWhileArmed setting ui->spinningArmed->setChecked(actuatorSettingsData.MotorsSpinWhileArmed == ActuatorSettings::MOTORSSPINWHILEARMED_TRUE); - // Setup output rates for all banks - if (ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[0])) == -1) { - ui->cb_outputRate1->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[0])); - } - if (ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[1])) == -1) { - ui->cb_outputRate2->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[1])); - } - if (ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[2])) == -1) { - ui->cb_outputRate3->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[2])); - } - if (ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[3])) == -1) { - ui->cb_outputRate4->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[3])); - } - if (ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[4])) == -1) { - ui->cb_outputRate5->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[4])); - } - if (ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[5])) == -1) { - ui->cb_outputRate6->addItem(QString::number(actuatorSettingsData.ChannelUpdateFreq[5])); - } - ui->cb_outputRate1->setCurrentIndex(ui->cb_outputRate1->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[0]))); - ui->cb_outputRate2->setCurrentIndex(ui->cb_outputRate2->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[1]))); - ui->cb_outputRate3->setCurrentIndex(ui->cb_outputRate3->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[2]))); - ui->cb_outputRate4->setCurrentIndex(ui->cb_outputRate4->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[3]))); - ui->cb_outputRate5->setCurrentIndex(ui->cb_outputRate5->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[4]))); - ui->cb_outputRate6->setCurrentIndex(ui->cb_outputRate6->findText(QString::number(actuatorSettingsData.ChannelUpdateFreq[5]))); + QList bank; + bank << ui->chBank1 << ui->chBank2 << ui->chBank3 << ui->chBank4 << ui->chBank5 << ui->chBank6; - // Reset to all disabled - ui->chBank1->setText("-"); - ui->chBank2->setText("-"); - ui->chBank3->setText("-"); - ui->chBank4->setText("-"); - ui->chBank5->setText("-"); - ui->chBank6->setText("-"); - ui->cb_outputRate1->setEnabled(false); - ui->cb_outputRate2->setEnabled(false); - ui->cb_outputRate3->setEnabled(false); - ui->cb_outputRate4->setEnabled(false); - ui->cb_outputRate5->setEnabled(false); - ui->cb_outputRate6->setEnabled(false); + QList outputRateCombos; + outputRateCombos << ui->cb_outputRate1 << ui->cb_outputRate2 << ui->cb_outputRate3 << + ui->cb_outputRate4 << ui->cb_outputRate5 << ui->cb_outputRate6; + + QList outputModeCombos; + outputModeCombos << ui->cb_outputMode1 << ui->cb_outputMode2 << ui->cb_outputMode3 << + ui->cb_outputMode4 << ui->cb_outputMode5 << ui->cb_outputMode6; + + Q_ASSERT(outputModeCombos.count() == outputRateCombos.count()); + Q_ASSERT(outputRateCombos.count() == bank.count()); + + for (int i = 0; i < outputModeCombos.count(); i++) { + // Setup output rates for all banks + if (outputRateCombos.at(i)->findText(QString::number(actuatorSettingsData.BankUpdateFreq[i])) == -1) { + outputRateCombos.at(i)->addItem(QString::number(actuatorSettingsData.BankUpdateFreq[i])); + } + outputRateCombos.at(i)->setCurrentIndex(outputRateCombos.at(i)->findText(QString::number(actuatorSettingsData.BankUpdateFreq[i]))); + + // Reset to all disabled + bank.at(i)->setText("-"); + + outputRateCombos.at(i)->setEnabled(false); + setColor(outputRateCombos.at(i), palette().color(QPalette::Background)); + + outputModeCombos.at(i)->setEnabled(false); + setColor(outputModeCombos.at(i), palette().color(QPalette::Background)); + } // Get connected board model ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); Q_ASSERT(pm); UAVObjectUtilManager *utilMngr = pm->getObject(); Q_ASSERT(utilMngr); + QStringList bankLabels; if (utilMngr) { int board = utilMngr->getBoardModel(); // Setup labels and combos for banks according to board type if ((board & 0xff00) == 0x0400) { // Coptercontrol family of boards 4 timer banks - ui->chBank1->setText("1-3"); - ui->chBank2->setText("4"); - ui->chBank3->setText("5,7-8"); - ui->chBank4->setText("6,9-10"); - ui->cb_outputRate1->setEnabled(true); - ui->cb_outputRate2->setEnabled(true); - ui->cb_outputRate3->setEnabled(true); - ui->cb_outputRate4->setEnabled(true); + bankLabels << "1 (1-3)" << "2 (4)" << "3 (5,7-8)" << "4 (6,9-10)"; + channelBanks << 1 << 1 << 1 << 2 << 3 << 4 << 3 << 3 << 4 << 4; } else if ((board & 0xff00) == 0x0900) { // Revolution family of boards 6 timer banks - ui->chBank1->setText("1-2"); - ui->chBank2->setText("3"); - ui->chBank3->setText("4"); - ui->chBank4->setText("5-6"); - ui->chBank5->setText("7-8"); - ui->chBank6->setText("9-10"); - ui->cb_outputRate1->setEnabled(true); - ui->cb_outputRate2->setEnabled(true); - ui->cb_outputRate3->setEnabled(true); - ui->cb_outputRate4->setEnabled(true); - ui->cb_outputRate5->setEnabled(true); - ui->cb_outputRate6->setEnabled(true); + bankLabels << "1 (1-2)" << "2 (3)" << "3 (4)" << "4 (5-6)" << "5 (7-8)" << "6 (9-10)"; + channelBanks << 1 << 1 << 2 << 3 << 4 << 4 << 5 << 5 << 6 << 6; } } + int i = 0; + foreach(QString banklabel, bankLabels) { + bank[i]->setText(banklabel); + outputRateCombos[i]->setEnabled(true); + setColor(outputRateCombos[i], bankColors[i]); + outputModeCombos[i]->setEnabled(true); + setColor(outputModeCombos[i], bankColors[i]); + i++; + } // Get Channel ranges: + i = 0; foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; outputChannelForm->setRange(minValue, maxValue); - + if (channelBanks.count() > i) { + outputChannelForm->setBank(QString("%1").arg(channelBanks.at(i))); + outputChannelForm->setColor(bankColors[channelBanks.at(i++) - 1]); + } int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; outputChannelForm->setNeutral(neutral); } @@ -374,7 +394,7 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) */ void ConfigOutputWidget::updateObjectsFromWidgets() { - emit updateObjectsFromWidgetsRequested(); + ConfigTaskWidget::updateObjectsFromWidgets(); ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager()); @@ -391,12 +411,12 @@ void ConfigOutputWidget::updateObjectsFromWidgets() } // Set update rates - actuatorSettingsData.ChannelUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); - actuatorSettingsData.ChannelUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[0] = ui->cb_outputRate1->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[1] = ui->cb_outputRate2->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[2] = ui->cb_outputRate3->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[3] = ui->cb_outputRate4->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[4] = ui->cb_outputRate5->currentText().toUInt(); + actuatorSettingsData.BankUpdateFreq[5] = ui->cb_outputRate6->currentText().toUInt(); actuatorSettingsData.MotorsSpinWhileArmed = ui->spinningArmed->isChecked() ? ActuatorSettings::MOTORSSPINWHILEARMED_TRUE : diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h index bb1d37c27..3b25fed69 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h @@ -59,6 +59,8 @@ private: void assignOutputChannel(UAVDataObject *obj, QString &str); + void setColor(QWidget *widget, const QColor color); + OutputChannelForm *getOutputChannelForm(const int index) const; void sendAllChannelTests(); diff --git a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp index 02ecb5b65..198753877 100644 --- a/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp @@ -94,6 +94,7 @@ QStringList ConfigVehicleTypeWidget::getChannelDescriptions() case SystemSettings::AIRFRAMETYPE_HEXAX: case SystemSettings::AIRFRAMETYPE_HEXACOAX: case SystemSettings::AIRFRAMETYPE_HEXA: + case SystemSettings::AIRFRAMETYPE_HEXAH: // multirotor channelDesc = ConfigMultiRotorWidget::getChannelDescriptions(); break; diff --git a/ground/openpilotgcs/src/plugins/config/pipxtreme.ui b/ground/openpilotgcs/src/plugins/config/oplink.ui similarity index 95% rename from ground/openpilotgcs/src/plugins/config/pipxtreme.ui rename to ground/openpilotgcs/src/plugins/config/oplink.ui index 9cbe0265c..9e462577f 100644 --- a/ground/openpilotgcs/src/plugins/config/pipxtreme.ui +++ b/ground/openpilotgcs/src/plugins/config/oplink.ui @@ -49,8 +49,8 @@ 0 0 - 949 - 558 + 812 + 566 @@ -312,44 +312,6 @@ - - - - - 50 - false - - - - Channel Set - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 60 - 16777215 - - - - - 50 - false - - - - Sets the random sequence of channels to use for frequency hopping. - - - 250 - - - @@ -911,6 +873,374 @@ + + + + + 50 + false + + + + RX Corrected + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + RX Seq. No. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 50 + false + + + + RX Rate (B/s) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 50 + false + + + + RX Good + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 101 + 16777215 + + + + + 50 + false + + + + The percentage of packets that were corrected with error correction + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + 50 + false + + + + RX Errors + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 101 + 16777215 + + + + + 50 + false + + + + The percentage of packets that were corrected with error correction + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + 50 + false + + + + RX Missed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + UAVTalk Errors + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 0 + 0 + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 50 + false + + + + Resets + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 101 + 16777215 + + + + + 50 + false + + + + false + + + true + + + + + + + + 50 + false + + + + Timeouts + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -1066,34 +1396,19 @@ - - - - - 0 - 0 - - - - - 101 - 16777215 - - + + 50 false - - The number of packets that were unable to be transmitted + + TX Rate (B/s) - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -1141,254 +1456,6 @@ - - - - - 50 - false - - - - TX Rate (B/s) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 101 - 16777215 - - - - - 50 - false - - - - false - - - true - - - - - - - - 50 - false - - - - RX Seq. No. - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 101 - 16777215 - - - - - 50 - false - - - - false - - - true - - - - - - - - 50 - false - - - - RX Rate (B/s) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 101 - 16777215 - - - - - 50 - false - - - - false - - - true - - - - - - - - 50 - false - - - - RX Good - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 101 - 16777215 - - - - - 50 - false - - - - The percentage of packets that were corrected with error correction - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - 50 - false - - - - RX Corrected - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 101 - 16777215 - - - - - 50 - false - - - - The percentage of packets that were corrected with error correction - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - 50 - false - - - - RX Errors - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -1420,22 +1487,6 @@ - - - - - 50 - false - - - - RX Missed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -1473,107 +1524,6 @@ - - - - - 50 - false - - - - TX Dropped - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 101 - 16777215 - - - - - 50 - false - - - - The number of packets that were unable to be transmitted - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - 50 - false - - - - TX Resent - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Tx Failure - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 101 - 16777215 - - - - - 50 - false - - - - false - - - true - - - @@ -1609,24 +1559,8 @@ - - - - - 50 - false - - - - UAVTalk Errors - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - + + 101 @@ -1647,13 +1581,29 @@ - - - - - 0 - 0 - + + + + + 50 + false + + + + Tx Failure + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + @@ -1667,16 +1617,19 @@ false - - false + + The number of packets that were unable to be transmitted + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true - - + + 50 @@ -1684,52 +1637,14 @@ - Resets + TX Dropped Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 101 - 16777215 - - - - - 50 - false - - - - false - - - true - - - - - - - - 50 - false - - - - Timeouts - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + @@ -1745,7 +1660,7 @@ - + diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index e80ea0764..f804aab1d 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -122,8 +122,8 @@ 0 0 - 674 - 677 + 680 + 672 @@ -157,7 +157,7 @@ - Output Update Speed + Output configuration @@ -183,7 +183,7 @@ - Channel: + Bank(Channels): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -282,9 +282,15 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + false + + + + 50 @@ -345,8 +351,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -430,8 +438,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -493,8 +503,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -566,8 +578,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -629,8 +643,10 @@ - Setup "RapidESC" here: usual value is 490 Hz for multirotor airframes. - + Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value + + + @@ -674,6 +690,190 @@ + + + + + 0 + 0 + + + + + 0 + 20 + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + Mode: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs. +Several other ESCs like BLHeli 13+ can use the more advanced OneShot125. +When using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + + + + + false + + + + 0 + 0 + + + + + 0 + 20 + + + + Setup output mode. Use PWM or OneShot with Standard ESCs.\nSeveral other ESCs like BLHeli 13+ can use the more advanced OneShot125.\nWhen using OneShot125 all values set in min/max and idle are divided by eight before being sent to esc (i.e. 1000 = 125, 2000 = 250). + + + diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index 0ca1ecaf7..8732aa43d 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -33,8 +33,8 @@ OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : ui.setupUi(this); // The convention for OP is Channel 1 to Channel 10. - ui.actuatorNumber->setText(QString("%1:").arg(index + 1)); - + ui.actuatorNumber->setText(QString("%1").arg(index + 1)); + setBank("-"); // Register for ActuatorSettings changes: connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); connect(ui.actuatorMax, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); @@ -58,6 +58,11 @@ QString OutputChannelForm::name() return ui.actuatorName->text(); } +QString OutputChannelForm::bank() +{ + return ui.actuatorBankNumber->text(); +} + /** * Set the channel assignment label. */ @@ -66,6 +71,25 @@ void OutputChannelForm::setName(const QString &name) ui.actuatorName->setText(name); } +void OutputChannelForm::setColor(const QColor &color) +{ + QString stylesheet = ui.actuatorNumberFrame->styleSheet(); + + stylesheet = stylesheet.split("background-color").first(); + stylesheet.append( + QString("background-color: rgb(%1, %2, %3)") + .arg(color.red()).arg(color.green()).arg(color.blue())); + ui.actuatorNumberFrame->setStyleSheet(stylesheet); +} + +/** + * Set the channel bank label. + */ +void OutputChannelForm::setBank(const QString &bank) +{ + ui.actuatorBankNumber->setText(bank); +} + /** * Restrict UI to protect users from accidental misuse. */ diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index 78d008115..e17155f41 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -43,8 +43,12 @@ public: friend class ConfigOutputWidget; virtual QString name(); - virtual void setName(const QString &name); + virtual QString bank(); + virtual void setName(const QString &name); + virtual void setBank(const QString &bank); + + virtual void setColor(const QColor &color); public slots: int min() const; void setMin(int minimum); diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index f6227939a..459841ace 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -7,7 +7,7 @@ 0 0 768 - 51 + 54 @@ -29,7 +29,7 @@ 12 - + @@ -72,7 +72,7 @@ margin:1px; - + @@ -115,7 +115,7 @@ margin:1px; - + @@ -152,7 +152,7 @@ margin:1px; - + Qt::Horizontal @@ -168,7 +168,7 @@ margin:1px; - + @@ -207,7 +207,7 @@ font: bold 12px; margin:1px; - # + # - Bank Qt::AlignCenter @@ -217,7 +217,7 @@ margin:1px; - + Qt::Horizontal @@ -233,7 +233,7 @@ margin:1px; - + Qt::Horizontal @@ -249,7 +249,7 @@ margin:1px; - + Qt::Horizontal @@ -265,7 +265,7 @@ margin:1px; - + @@ -289,7 +289,8 @@ margin:1px; Qt::StrongFocus - Minimum PWM value, beware of not overdriving your servo. + Minimum PWM value, beware of not overdriving your servo. +Using OneShot125 a value of 1000(uS) here will produce a pulse of 125(uS). Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -302,38 +303,151 @@ margin:1px; - - + + 0 0 - - - 20 - 0 - - - 16777215 - 16777215 + 100 + 22 - - Channel Number + + border-radius: 5; margin:1px; - - 0: + + QFrame::NoFrame - - Qt::AlignCenter + + QFrame::Raised + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + + + + Channel Number + + + border-radius: 5;\nfont: bold 12px;\nmargin:1px; + + + 0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + border-radius: 5;\nfont: 12px;\nmargin:1px; + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + Bank number + + + border-radius: 5;\nfont: 12px;\nmargin:1px; + + + 0 + + + Qt::AlignCenter + + + + - + @@ -376,7 +490,7 @@ margin:1px; - + @@ -419,7 +533,7 @@ margin:1px; - + @@ -462,7 +576,7 @@ margin:1px; - + @@ -490,7 +604,7 @@ margin:1px; - + @@ -514,7 +628,8 @@ margin:1px; Qt::StrongFocus - Maximum PWM value, beware of not overdriving your servo. + Maximum value, beware of not overdriving your servo. +Using OneShot125 a value of 2000(uS) here will produce a pulse of 250(uS). Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -524,8 +639,8 @@ margin:1px; - - + + 0 @@ -607,7 +722,7 @@ margin:1px; - + @@ -665,7 +780,7 @@ margin:1px; - + diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h index 30366338a..7828773cd 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h @@ -33,9 +33,6 @@ #include #include #include -#if defined(Q_OS_LINUX) -#include -#endif #include "../hidapi/hidapi.h" #include "ophid_const.h" #include "ophid_global.h" diff --git a/ground/openpilotgcs/src/plugins/ophid/ophid.pro b/ground/openpilotgcs/src/plugins/ophid/ophid.pro index bad70ea7a..f882d9198 100644 --- a/ground/openpilotgcs/src/plugins/ophid/ophid.pro +++ b/ground/openpilotgcs/src/plugins/ophid/ophid.pro @@ -38,38 +38,20 @@ macx { -framework IOKit } -linux-g++ { +linux { SOURCES += src/ophid_usbmon_linux.cpp - LIBS += -lusb -ludev + LIBS += -ludev -lrt -lpthread # hidapi library ## rawhid # SOURCES += hidapi/linux/hid.c ## libusb SOURCES += hidapi/libusb/hid.c - LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread - INCLUDEPATH += /usr/include/libusb-1.0 -# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` + + CONFIG += link_pkgconfig + PKGCONFIG += libusb-1.0 !exists(/usr/include/libusb-1.0) { - error(Install libusb-1.0.0-dev using your package manager.) + error(Install libusb-1.0-0-dev using your package manager.) } } - -linux-g++-64 { - SOURCES += src/ophid_usbmon_linux.cpp - LIBS += -lusb -ludev - - # hidapi library - ## rawhid - # SOURCES += hidapi/linux/hid.c - ## libusb - SOURCES += hidapi/libusb/hid.c - LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread - INCLUDEPATH += /usr/include/libusb-1.0 -# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` - !exists(/usr/include/libusb-1.0) { - error(Install libusb-1.0.0-dev using your package manager.) - } -} - diff --git a/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.cpp b/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.cpp index 6655351bb..ee0444023 100644 --- a/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.cpp +++ b/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.cpp @@ -103,39 +103,39 @@ modelMapProxy::overlayType modelMapProxy::overlayTranslate(int type) } } -void modelMapProxy::createOverlay(WayPointItem *from, WayPointItem *to, modelMapProxy::overlayType type, QColor color) +void modelMapProxy::createOverlay(WayPointItem *from, WayPointItem *to, modelMapProxy::overlayType type, QColor color, bool dashed, int width) { if (from == NULL || to == NULL || from == to) { return; } switch (type) { case OVERLAY_LINE: - myMap->WPLineCreate(from, to, color); + myMap->WPLineCreate(from, to, color, dashed, width); break; case OVERLAY_CIRCLE_RIGHT: - myMap->WPCircleCreate(to, from, true, color); + myMap->WPCircleCreate(to, from, true, color, dashed, width); break; case OVERLAY_CIRCLE_LEFT: - myMap->WPCircleCreate(to, from, false, color); + myMap->WPCircleCreate(to, from, false, color, dashed, width); break; default: break; } } -void modelMapProxy::createOverlay(WayPointItem *from, HomeItem *to, modelMapProxy::overlayType type, QColor color) +void modelMapProxy::createOverlay(WayPointItem *from, HomeItem *to, modelMapProxy::overlayType type, QColor color, bool dashed, int width) { if (from == NULL || to == NULL) { return; } switch (type) { case OVERLAY_LINE: - myMap->WPLineCreate(to, from, color); + myMap->WPLineCreate(to, from, color, dashed, width); break; case OVERLAY_CIRCLE_RIGHT: - myMap->WPCircleCreate(to, from, true, color); + myMap->WPCircleCreate(to, from, true, color, dashed, width); break; case OVERLAY_CIRCLE_LEFT: - myMap->WPCircleCreate(to, from, false, color); + myMap->WPCircleCreate(to, from, false, color, dashed, width); break; default: break; @@ -164,7 +164,7 @@ void modelMapProxy::refreshOverlays() wp_next_overlay = overlayTranslate(model->data(model->index(x + 1, flightDataModel::MODE)).toInt()); wp_jump_overlay = overlayTranslate(model->data(model->index(wp_jump, flightDataModel::MODE)).toInt()); wp_error_overlay = overlayTranslate(model->data(model->index(wp_error, flightDataModel::MODE)).toInt()); - createOverlay(wp_current, findWayPointNumber(wp_error), wp_error_overlay, Qt::red); + createOverlay(wp_current, findWayPointNumber(wp_error), wp_error_overlay, Qt::red, true, 1); switch (model->data(model->index(x, flightDataModel::COMMAND)).toInt()) { case MapDataDelegate::COMMAND_ONCONDITIONNEXTWAYPOINT: wp_next = findWayPointNumber(x + 1); diff --git a/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.h b/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.h index 04269c9ba..0c169698a 100644 --- a/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.h +++ b/ground/openpilotgcs/src/plugins/opmap/modelmapproxy.h @@ -56,8 +56,8 @@ private slots: void selectedWPChanged(QList); private: overlayType overlayTranslate(int type); - void createOverlay(WayPointItem *from, WayPointItem *to, overlayType type, QColor color); - void createOverlay(WayPointItem *from, HomeItem *to, modelMapProxy::overlayType type, QColor color); + void createOverlay(WayPointItem *from, WayPointItem *to, overlayType type, QColor color, bool dashed = false, int width = -1); + void createOverlay(WayPointItem *from, HomeItem *to, modelMapProxy::overlayType type, QColor color, bool dashed = false, int width = -1); OPMapWidget *myMap; flightDataModel *model; void refreshOverlays(); diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp index 2a66485f5..81bf4fd40 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp @@ -404,32 +404,32 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_FALSE; - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = LEGACY_ESC_FREQUENCY; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = LEGACY_ESC_FREQUENCY; } switch (m_configSource->getVehicleSubType()) { case VehicleConfigurationSource::MULTI_ROTOR_TRI_Y: // Servo always on channel 4 - data.ChannelUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC || m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC3D) { - data.ChannelUpdateFreq[1] = servoFrequence; + data.BankUpdateFreq[1] = servoFrequence; } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = servoFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = servoFrequence; } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = escFrequence; - data.ChannelUpdateFreq[3] = servoFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[3] = servoFrequence; } break; case VehicleConfigurationSource::MULTI_ROTOR_QUAD_X: case VehicleConfigurationSource::MULTI_ROTOR_QUAD_PLUS: - data.ChannelUpdateFreq[0] = escFrequence; - data.ChannelUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[1] = escFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { - data.ChannelUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; } break; case VehicleConfigurationSource::MULTI_ROTOR_HEXA: @@ -441,10 +441,10 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() case VehicleConfigurationSource::MULTI_ROTOR_OCTO_COAX_X: case VehicleConfigurationSource::MULTI_ROTOR_OCTO_COAX_PLUS: case VehicleConfigurationSource::MULTI_ROTOR_OCTO_V: - data.ChannelUpdateFreq[0] = escFrequence; - data.ChannelUpdateFreq[1] = escFrequence; - data.ChannelUpdateFreq[2] = escFrequence; - data.ChannelUpdateFreq[3] = escFrequence; + data.BankUpdateFreq[0] = escFrequence; + data.BankUpdateFreq[1] = escFrequence; + data.BankUpdateFreq[2] = escFrequence; + data.BankUpdateFreq[3] = escFrequence; break; default: break; @@ -467,15 +467,15 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.ChannelMax[i] = actuatorSettings[i].channelMax; } - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = servoFrequence; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = servoFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { if (i == 1) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { if (i == 2) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } } @@ -503,15 +503,15 @@ void VehicleConfigurationHelper::applyActuatorConfiguration() data.ChannelMax[i] = actuatorSettings[i].channelMax; } - for (quint16 i = 0; i < ActuatorSettings::CHANNELUPDATEFREQ_NUMELEM; i++) { - data.ChannelUpdateFreq[i] = servoFrequence; + for (quint16 i = 0; i < ActuatorSettings::BANKUPDATEFREQ_NUMELEM; i++) { + data.BankUpdateFreq[i] = servoFrequence; if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) { if (i == 1) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_NANO) { if (i == 2) { - data.ChannelUpdateFreq[i] = escFrequence; + data.BankUpdateFreq[i] = escFrequence; } } } diff --git a/package/Linux.mk b/package/Linux.mk index 1dca75269..458b31f77 100644 --- a/package/Linux.mk +++ b/package/Linux.mk @@ -20,8 +20,41 @@ DEB_PACKAGE_NAME := openpilot_$(DEB_VER)_$(DEB_ARCH) package: $(V1) echo "Building Linux package, please wait..." $(V1) cp -rL $(DEB_DIR) $(DEB_BUILD_DIR) - $(V1)sed -i -e "$(SED_SCRIPT)" $(DEB_BUILD_DIR)/changelog - $(V1) cd .. && dpkg-buildpackage -b -us -uc + $(V1) sed -i -e "$(SED_SCRIPT)" $(DEB_BUILD_DIR)/changelog + $(V1) dpkg-buildpackage -b -us -uc $(V1) mv $(ROOT_DIR)/../$(DEB_PACKAGE_NAME).deb $(BUILD_DIR)/$(DEB_PACKAGE_NAME).deb $(V1) mv $(ROOT_DIR)/../$(DEB_PACKAGE_NAME).changes $(BUILD_DIR)/$(DEB_PACKAGE_NAME).changes $(V1) rm -rf $(DEB_BUILD_DIR) + +############################## +# +# Install OpenPilot +# +############################## +prefix := /usr/local +bindir := $(prefix)/bin +libdir := $(prefix)/lib +datadir := $(prefix)/share + +INSTALL = cp -a --no-preserve=ownership +LN = ln +LN_S = ln -s + +.PHONY: install +install: + @$(ECHO) " INSTALLING GCS TO $(DESTDIR)/)" + $(V1) $(MKDIR) -p $(DESTDIR)$(bindir) + $(V1) $(MKDIR) -p $(DESTDIR)$(libdir) + $(V1) $(MKDIR) -p $(DESTDIR)$(datadir) + $(V1) $(MKDIR) -p $(DESTDIR)$(datadir)/applications + $(V1) $(MKDIR) -p $(DESTDIR)$(datadir)/pixmaps + $(V1) $(MKDIR) -p $(DESTDIR)$(udevdir) + $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/bin/openpilotgcs $(DESTDIR)$(bindir) + $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/bin/udp_test $(DESTDIR)$(bindir) + $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/lib/openpilotgcs $(DESTDIR)$(libdir) + $(V1) $(INSTALL) $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/share/openpilotgcs $(DESTDIR)$(datadir) + $(V1) $(INSTALL) $(ROOT_DIR)/package/linux/openpilot.desktop $(DESTDIR)$(datadir)/applications + $(V1) $(INSTALL) $(ROOT_DIR)/package/linux/openpilot.png $(DESTDIR)$(datadir)/pixmaps + $(V1) rm $(DESTDIR)/$(datadir)/openpilotgcs/translations/Makefile + + diff --git a/package/linux/debian/rules b/package/linux/debian/rules index 7bcf5650a..b67ae85e6 100644 --- a/package/linux/debian/rules +++ b/package/linux/debian/rules @@ -13,7 +13,7 @@ export DH_OPTIONS # Disabled because OpenPilot makefile cleans and builds. override_dh_auto_clean: - #$(MAKE) all_clean + # override_dh_auto_build: #dh_auto_build -- all diff --git a/shared/uavobjectdefinition/actuatorsettings.xml b/shared/uavobjectdefinition/actuatorsettings.xml index 051fdceb1..303770f4d 100644 --- a/shared/uavobjectdefinition/actuatorsettings.xml +++ b/shared/uavobjectdefinition/actuatorsettings.xml @@ -1,7 +1,15 @@ Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType - + + diff --git a/shared/uavobjectdefinition/oplinkreceiver.xml b/shared/uavobjectdefinition/oplinkreceiver.xml index 5323d1522..aa4b91db9 100644 --- a/shared/uavobjectdefinition/oplinkreceiver.xml +++ b/shared/uavobjectdefinition/oplinkreceiver.xml @@ -3,8 +3,8 @@ A receiver channel group carried over the OPLink radio. - - + + diff --git a/shared/uavobjectdefinition/oplinksettings.xml b/shared/uavobjectdefinition/oplinksettings.xml index b0f629acc..ac631616c 100644 --- a/shared/uavobjectdefinition/oplinksettings.xml +++ b/shared/uavobjectdefinition/oplinksettings.xml @@ -13,7 +13,6 @@ - diff --git a/shared/uavobjectdefinition/oplinkstatus.xml b/shared/uavobjectdefinition/oplinkstatus.xml index 07fda4375..5a225ff28 100644 --- a/shared/uavobjectdefinition/oplinkstatus.xml +++ b/shared/uavobjectdefinition/oplinkstatus.xml @@ -13,7 +13,6 @@ -