1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-15 07:29:15 +01:00

Merge remote-tracking branch 'origin/next' into samguns/zh_CN_GCS

This commit is contained in:
Laurent Lalanne 2015-02-15 10:16:28 +01:00
commit 9344351665
70 changed files with 2594 additions and 1216 deletions

117
Makefile
View File

@ -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"

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 KiB

View File

@ -32,6 +32,9 @@
#include <systemalarms.h>
#include <stdint.h>
#include <utlist.h>
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 */

View File

@ -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 <steve@edmweb.com>
* 100% Public Domain
*/
#ifndef _SYS_SHA1_H_
#define _SYS_SHA1_H_
#include <sys/cdefs.h>
#include <sys/types.h>
#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_ */

View File

@ -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;
}
}
}

279
flight/libraries/sha1.c Normal file
View File

@ -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 <steve@edmweb.com>
* 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 <sys/cdefs.h>
#if defined(_KERNEL) || defined(_STANDALONE)
__KERNEL_RCSID(0, "$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $");
#include <lib/libkern/libkern.h>
#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 <assert.h>
#include <string.h>
#endif
#include <stdint.h>
#include <sha1.h>
#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 */

View File

@ -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];
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 <pios_rfm22b_priv.h>
#include <pios_ppm_out.h>
#include <ecc.h>
#include <sha1.h>
/* 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 */
/**

View File

@ -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 */

View File

@ -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);

View File

@ -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;
};

View File

@ -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 */

View File

@ -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)
{}
/**

View File

@ -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]++;

View File

@ -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 */

View File

@ -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
*

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -247,6 +247,8 @@ extern uint32_t pios_com_telem_usb_id;
// --------------------------
#define PIOS_TIM_MAX_DEVS 6
#define PIOS_SERVO_BANKS 6
// -------------------------
// USB
// -------------------------

View File

@ -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

View File

@ -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);
}

View File

@ -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
// --------------------------

View File

@ -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

View File

@ -1551,6 +1551,17 @@
<enableVbo>false</enableVbo>
</data>
</Revolution>
<Blackout_MiniH>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/blackout/BlackoutMiniHQuad.3DS</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Blackout_MiniH>
<Zagi>
<configInfo>
<locked>false</locked>
@ -2530,7 +2541,7 @@
<side0>
<classId>ModelViewGadget</classId>
<gadget>
<activeConfiguration>Test Quad X</activeConfiguration>
<activeConfiguration>Blackout_MiniH</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 KiB

View File

@ -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;
}

View File

@ -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();

View File

@ -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<qreal> dashes;
dashes << 4 << 8;
myPen.setDashPattern(dashes);
}
qreal arrowSize = 10;
painter->setPen(myPen);
QBrush brush = painter->brush();

View File

@ -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:

View File

@ -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<qreal> 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());

View File

@ -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:

View File

@ -511,7 +511,7 @@ Typical value is 50% for + or X configuration on quads.</string>
<property name="title">
<string>Motor output channels</string>
</property>
<layout class="QGridLayout" name="gridLayout_7" columnstretch="1,1,0,0,1">
<layout class="QGridLayout" name="gridLayout_7" columnstretch="1,1,0,0,1,0,0">
<property name="leftMargin">
<number>9</number>
</property>
@ -524,61 +524,41 @@ Typical value is 50% for + or X configuration on quads.</string>
<property name="bottomMargin">
<number>9</number>
</property>
<item row="0" column="0" rowspan="5">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="6" rowspan="5">
<layout class="QGridLayout" name="gridLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
<property name="leftMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="MotorOutputLabel1_2">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox1">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox2">
<widget class="QComboBox" name="rcOutputChannelBox1">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
<string>Select output channel for Accessory0 RcInput</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<widget class="QLabel" name="label_8">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>3</string>
<string>Accessory1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox3">
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
<string>RcOutput channels</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_15">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>4</string>
<string>RC Output</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>Accessory0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>RC Input</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox4">
<widget class="QComboBox" name="rcOutputChannelBox3">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
<string>Select output channel for Accessory2 RcInput</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="rcOutputChannelBox2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Select output channel for Accessory1 RcInput</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>Accessory2</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_10">
<property name="toolTip">
<string>RcOutput curve</string>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>Curve</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="rcOutputCurveBox1">
<property name="toolTip">
<string>Select output curve for Accessory0 RcInput</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="rcOutputCurveBox2">
<property name="toolTip">
<string>Select output curve for Accessory1 RcInput</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="rcOutputCurveBox3">
<property name="toolTip">
<string>Select output curve for Accessory2 RcInput</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>Tricopter Yaw Servo channel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="5">
<layout class="QFormLayout" name="formLayout_5">
<property name="sizeConstraint">
@ -749,7 +925,143 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="2" column="4">
<item row="1" column="4">
<widget class="QComboBox" name="triYawChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="5">
<layout class="QFormLayout" name="formLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="MotorOutputLabel1_2">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox1">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox2">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox3">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_15">
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox4">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="5" rowspan="5">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QCheckBox" name="MultirotorRevMixerCheckBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Reverse all motors</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -778,61 +1090,6 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QComboBox" name="triYawChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">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;</string>
</property>
<property name="text">
<string>Tricopter Yaw Servo channel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QCheckBox" name="MultirotorRevMixerCheckBox">
<property name="text">
<string>Reverse all motors</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -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<UAVDataObject *>(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<UAVDataObject *>(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<QString> 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<QString> rcOutputList)
{
QList<QComboBox *> rcList;
rcList << m_aircraft->rcOutputChannelBox1 << m_aircraft->rcOutputChannelBox2 << m_aircraft->rcOutputChannelBox3;
GUIConfigDataUnion configData = getConfigData();
resetRcOutputs(&configData);
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(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<QComboBox *>("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<QComboBox *>("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();
}
}

View File

@ -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<QString> motorList);
void setupRcOutputs(QList<QString> 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);

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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] =

View File

@ -25,7 +25,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "configpipxtremewidget.h"
#include "configoplinkwidget.h"
#include <coreplugin/generalsettings.h>
#include <oplinksettings.h>
@ -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<QPushButton *>(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();

View File

@ -29,15 +29,15 @@
#include <oplinksettings.h>
#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);

View File

@ -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<int> channelBanks;
QList<QColor> bankColors;
bankColors
<< QColor("#C6ECAE")
<< QColor("#91E5D3")
<< QColor("#FCEC52")
<< QColor("#C3A8FF")
<< QColor("#F7F7F2")
<< QColor("#FF9F51");
// Initialize output forms
QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
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<QLabel *> 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<QComboBox *> outputRateCombos;
outputRateCombos << ui->cb_outputRate1 << ui->cb_outputRate2 << ui->cb_outputRate3 <<
ui->cb_outputRate4 << ui->cb_outputRate5 << ui->cb_outputRate6;
QList<QComboBox *> 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<UAVObjectUtilManager>();
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 :

View File

@ -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();

View File

@ -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;

View File

@ -49,8 +49,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>949</width>
<height>558</height>
<width>812</width>
<height>566</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_5">
@ -312,44 +312,6 @@
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="ChannelSetLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Channel Set</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="ChannelSet">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Sets the random sequence of channels to use for frequency hopping.</string>
</property>
<property name="maximum">
<number>250</number>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QCheckBox" name="Coordinator">
<property name="font">
@ -911,6 +873,374 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="CorrectedLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Corrected</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="RXSeqLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Seq. No.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QLineEdit" name="TXRate">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QLabel" name="RXRateLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Rate (B/s)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QLineEdit" name="RXSeq">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QLineEdit" name="RXRate">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="GoodLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Good</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="Good">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The percentage of packets that were corrected with error correction</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ErrorsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Errors</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="Corrected">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The percentage of packets that were corrected with error correction</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="MissedPacketsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Missed</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="6">
<widget class="QLabel" name="UAVTalkErrorsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>UAVTalk Errors</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="7">
<widget class="QLineEdit" name="UAVTalkErrors">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="7">
<widget class="QLineEdit" name="Resets">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="6">
<widget class="QLabel" name="ResetsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Resets</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QLineEdit" name="Timeouts">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QLabel" name="TimeoutsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timeouts</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QLineEdit" name="RSSI">
<property name="minimumSize">
@ -1066,34 +1396,19 @@
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLineEdit" name="Resent">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<item row="2" column="6">
<widget class="QLabel" name="TXRateLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The number of packets that were unable to be transmitted</string>
<property name="text">
<string>TX Rate (B/s)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -1141,254 +1456,6 @@
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QLabel" name="TXRateLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>TX Rate (B/s)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QLineEdit" name="TXRate">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="RXSeqLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Seq. No.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QLineEdit" name="RXSeq">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QLabel" name="RXRateLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Rate (B/s)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QLineEdit" name="RXRate">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="GoodLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Good</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="Good">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The percentage of packets that were corrected with error correction</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="CorrectedLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Corrected</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="Corrected">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The percentage of packets that were corrected with error correction</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ErrorsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Errors</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="Errors">
<property name="sizePolicy">
@ -1420,22 +1487,6 @@
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="MissedPacketsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>RX Missed</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="Missed">
<property name="sizePolicy">
@ -1473,107 +1524,6 @@
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="DroppedLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>TX Dropped</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="Dropped">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>The number of packets that were unable to be transmitted</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="ResentLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>TX Resent</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="TxFailureLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Tx Failure</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLineEdit" name="TxFailure">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QLabel" name="FreeHeapLabel">
<property name="font">
@ -1609,24 +1559,8 @@
</property>
</widget>
</item>
<item row="5" column="6">
<widget class="QLabel" name="UAVTalkErrorsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>UAVTalk Errors</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="7">
<widget class="QLineEdit" name="UAVTalkErrors">
<item row="3" column="3">
<widget class="QLineEdit" name="TxFailure">
<property name="maximumSize">
<size>
<width>101</width>
@ -1647,13 +1581,29 @@
</property>
</widget>
</item>
<item row="6" column="7">
<widget class="QLineEdit" name="Resets">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
<item row="3" column="2">
<widget class="QLabel" name="TxFailureLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Tx Failure</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="Dropped">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
@ -1667,16 +1617,19 @@
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
<property name="toolTip">
<string>The number of packets that were unable to be transmitted</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="6">
<widget class="QLabel" name="ResetsLabel">
<item row="2" column="2">
<widget class="QLabel" name="ResentLabel">
<property name="font">
<font>
<weight>50</weight>
@ -1684,52 +1637,14 @@
</font>
</property>
<property name="text">
<string>Resets</string>
<string>TX Dropped</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QLineEdit" name="Timeouts">
<property name="maximumSize">
<size>
<width>101</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QLabel" name="TimeoutsLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timeouts</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2">
<item row="7" column="0">
<widget class="QLabel" name="RxFailureLabel">
<property name="font">
<font>
@ -1745,7 +1660,7 @@
</property>
</widget>
</item>
<item row="6" column="3">
<item row="7" column="1">
<widget class="QLineEdit" name="RxFailure">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">

View File

@ -122,8 +122,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>674</width>
<height>677</height>
<width>680</width>
<height>672</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -157,7 +157,7 @@
</size>
</property>
<property name="title">
<string>Output Update Speed</string>
<string>Output configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="6">
@ -183,7 +183,7 @@
<item row="0" column="1">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Channel:</string>
<string>Bank(Channels):</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -282,9 +282,15 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value
</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
<string>50</string>
@ -345,8 +351,10 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
</string>
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
@ -430,8 +438,10 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
</string>
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
@ -493,8 +503,10 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
</string>
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
@ -566,8 +578,10 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
</string>
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
@ -629,8 +643,10 @@
</size>
</property>
<property name="toolTip">
<string>Setup &quot;RapidESC&quot; here: usual value is 490 Hz for multirotor airframes.
</string>
<string>Setup PWM rate here: usual value is 490 Hz for multirotor airframes. OneShot and OneShot125 does not use this value</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
@ -674,6 +690,190 @@
</item>
</widget>
</item>
<item row="2" column="0">
<spacer name="horizontalSpacer_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Mode:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="cb_outputMode1">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QComboBox" name="cb_outputMode2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QComboBox" name="cb_outputMode3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QComboBox" name="cb_outputMode4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QComboBox" name="cb_outputMode5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QComboBox" name="cb_outputMode6">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>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).</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -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.
*/

View File

@ -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);

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>768</width>
<height>51</height>
<height>54</height>
</rect>
</property>
<property name="windowTitle">
@ -29,7 +29,7 @@
<property name="horizontalSpacing">
<number>12</number>
</property>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QLabel" name="legend0">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -72,7 +72,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="2">
<item row="0" column="3">
<widget class="QLabel" name="legend1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -115,7 +115,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="4">
<item row="0" column="5">
<widget class="QLabel" name="legend2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -152,7 +152,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="5">
<item row="0" column="6">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -168,7 +168,7 @@ margin:1px;</string>
</property>
</spacer>
</item>
<item row="0" column="0">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="legend6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -207,7 +207,7 @@ font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>#</string>
<string> # - Bank</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@ -217,7 +217,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="3">
<item row="0" column="4">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -233,7 +233,7 @@ margin:1px;</string>
</property>
</spacer>
</item>
<item row="1" column="5">
<item row="1" column="6">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -249,7 +249,7 @@ margin:1px;</string>
</property>
</spacer>
</item>
<item row="1" column="3">
<item row="1" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -265,7 +265,7 @@ margin:1px;</string>
</property>
</spacer>
</item>
<item row="1" column="2">
<item row="1" column="3">
<widget class="QSpinBox" name="actuatorMin">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -289,7 +289,8 @@ margin:1px;</string>
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Minimum PWM value, beware of not overdriving your servo.</string>
<string>Minimum PWM value, beware of not overdriving your servo.
Using OneShot125 a value of 1000(uS) here will produce a pulse of 125(uS).</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -302,38 +303,151 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="actuatorNumber">
<item row="1" column="0" colspan="2">
<widget class="QFrame" name="actuatorNumberFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
<width>100</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Channel Number</string>
<property name="styleSheet">
<string notr="true">border-radius: 5; margin:1px;</string>
</property>
<property name="text">
<string>0:</string>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="actuatorNumber">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>Channel Number</string>
</property>
<property name="styleSheet">
<string notr="true">border-radius: 5;\nfont: bold 12px;\nmargin:1px;</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">border-radius: 5;\nfont: 12px;\nmargin:1px;</string>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="actuatorBankNumber">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Bank number</string>
</property>
<property name="styleSheet">
<string notr="true">border-radius: 5;\nfont: 12px;\nmargin:1px;</string>
</property>
<property name="text">
<string> 0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="6">
<item row="0" column="7">
<widget class="QLabel" name="legend3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -376,7 +490,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="7">
<item row="0" column="8">
<widget class="QLabel" name="legend4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -419,7 +533,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="0" column="8">
<item row="0" column="9">
<widget class="QLabel" name="legend5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -462,7 +576,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="1" column="2">
<widget class="QLabel" name="actuatorName">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@ -490,7 +604,7 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="1" column="6">
<item row="1" column="7">
<widget class="QSpinBox" name="actuatorMax">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -514,7 +628,8 @@ margin:1px;</string>
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Maximum PWM value, beware of not overdriving your servo.</string>
<string>Maximum value, beware of not overdriving your servo.
Using OneShot125 a value of 2000(uS) here will produce a pulse of 250(uS).</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -524,8 +639,8 @@ margin:1px;</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QFrame" name="frame">
<item row="1" column="5">
<widget class="QFrame" name="barFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -607,7 +722,7 @@ margin:1px;</string>
</layout>
</widget>
</item>
<item row="1" column="7">
<item row="1" column="8">
<widget class="QFrame" name="frame_1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@ -665,7 +780,7 @@ margin:1px;</string>
</layout>
</widget>
</item>
<item row="1" column="8">
<item row="1" column="9">
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">

View File

@ -33,9 +33,6 @@
#include <QDebug>
#include <QString>
#include <QMutex>
#if defined(Q_OS_LINUX)
#include <usb.h>
#endif
#include "../hidapi/hidapi.h"
#include "ophid_const.h"
#include "ophid_global.h"

View File

@ -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.)
}
}

View File

@ -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);

View File

@ -56,8 +56,8 @@ private slots:
void selectedWPChanged(QList<WayPointItem *>);
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();

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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

View File

@ -1,7 +1,15 @@
<xml>
<object name="ActuatorSettings" singleinstance="true" settings="true" category="Control">
<description>Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType</description>
<field name="ChannelUpdateFreq" units="Hz" type="uint16" elements="6" defaultvalue="50"/>
<field name="BankUpdateFreq" units="Hz" type="uint16" elements="6" defaultvalue="50"/>
<field name="BankMode" type="enum" units="" elements="6" options="PWM,OneShot,OneShot125" defaultvalue="PWM"
limits="%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125; \
%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125; \
%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125; \
%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125; \
%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125; \
%0401NE:OneShot:OneShot125,%0402NE:OneShot:OneShot125;"
/>
<field name="ChannelMax" units="us" type="int16" elements="12" defaultvalue="1000"/>
<field name="ChannelNeutral" units="us" type="int16" elements="12" defaultvalue="1000"/>
<field name="ChannelMin" units="us" type="int16" elements="12" defaultvalue="1000"/>

View File

@ -3,8 +3,8 @@
<description>A receiver channel group carried over the OPLink radio.</description>
<field name="Channel" units="us" type="int16" elements="8"/>
<access gcs="readonly" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="onchange" period="0"/>
<telemetryflight acked="false" updatemode="onchange" period="0"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
<logging updatemode="manual" period="0"/>
</object>
</xml>

View File

@ -13,7 +13,6 @@
<field name="MaxRFPower" units="mW" type="enum" elements="1" options="0,1.25,1.6,3.16,6.3,12.6,25,50,100" defaultvalue="0"/>
<field name="MinChannel" units="" type="uint8" elements="1" defaultvalue="0"/>
<field name="MaxChannel" units="" type="uint8" elements="1" defaultvalue="250"/>
<field name="ChannelSet" units="" type="uint8" elements="1" defaultvalue="39"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>

View File

@ -13,7 +13,6 @@
<field name="RxMissed" units="%" type="uint8" elements="1" defaultvalue="0"/>
<field name="RxFailure" units="%" type="uint8" elements="1" defaultvalue="0"/>
<field name="UAVTalkErrors" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="TxResent" units="%" type="uint8" elements="1" defaultvalue="0"/>
<field name="TxDropped" units="%" type="uint8" elements="1" defaultvalue="0"/>
<field name="TxFailure" units="%" type="uint8" elements="1" defaultvalue="0"/>
<field name="Resets" units="" type="uint8" elements="1" defaultvalue="0"/>