mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-27 16:54:15 +01:00
Merge branch 'next' into os/GPS-on-CopterControl_next_v2
Conflicts: flight/OpenPilot/System/pios_board.c flight/OpenPilot/UAVObjects.inc shared/uavobjectdefinition/hwsettings.xml
This commit is contained in:
commit
53c098dd08
15
HISTORY.txt
15
HISTORY.txt
@ -1,5 +1,20 @@
|
|||||||
Short summary of changes. For a complete list see the git log.
|
Short summary of changes. For a complete list see the git log.
|
||||||
|
|
||||||
|
2011-09-12
|
||||||
|
Max rate now ONLY applies to attitude and axis lock mode. Manual rate is the
|
||||||
|
only term that limits the rate mode now (and in axis lock when you push stick
|
||||||
|
only manual rate applies). Also integrals are reset when unused.
|
||||||
|
|
||||||
|
2011-09-09
|
||||||
|
Some large updates to the input system. Now multiple receivers can be
|
||||||
|
connected at once. A wizard was added for configuring the input channels. A
|
||||||
|
specific collective pitch channel was added.
|
||||||
|
|
||||||
|
2011-09-04
|
||||||
|
Improvements to the failsafe handling code for inputs. PWM power off is now
|
||||||
|
detected properly. Powering on transmitter for Spektrum Satellite no longer
|
||||||
|
causes a glitch on servos.
|
||||||
|
|
||||||
2011-08-10
|
2011-08-10
|
||||||
Added Camera Stabilization and a gui to configure this. This is a software
|
Added Camera Stabilization and a gui to configure this. This is a software
|
||||||
selectable module from the GUI. However, a restart is required to make it
|
selectable module from the GUI. However, a restart is required to make it
|
||||||
|
@ -82,7 +82,7 @@ C: Sami Korhonen (Sambas)
|
|||||||
D: February 2011
|
D: February 2011
|
||||||
V: http://vimeo.com/20159015
|
V: http://vimeo.com/20159015
|
||||||
|
|
||||||
M: First Position Hold on a Fixed Wing
|
M: First CopterControl Position Hold on a Fixed Wing
|
||||||
C: Eric Price (Corvus Corax)
|
C: Eric Price (Corvus Corax)
|
||||||
D: March 2011
|
D: March 2011
|
||||||
V: http://www.youtube.com/watch?v=QtaefhmGbio
|
V: http://www.youtube.com/watch?v=QtaefhmGbio
|
||||||
@ -146,6 +146,12 @@ M: First CopterControl Flybared Heli funnel (4:18), loop (5:35)
|
|||||||
C: Sergey Solodennikov (alconaft43)
|
C: Sergey Solodennikov (alconaft43)
|
||||||
D: August 2011
|
D: August 2011
|
||||||
V: http://www.youtube.com/watch?v=8SrfIS7OkB4
|
V: http://www.youtube.com/watch?v=8SrfIS7OkB4
|
||||||
|
|
||||||
|
M: First CopterControl Return to Base Fixed Wing
|
||||||
|
C: Eric Price (Corvus Corax)
|
||||||
|
D: AUgust 2011
|
||||||
|
V: http://www.youtube.com/watch?v=CugI0oBSQn8
|
||||||
|
|
||||||
|
|
||||||
M: First Altitude Hold using Sonar
|
M: First Altitude Hold using Sonar
|
||||||
C:
|
C:
|
||||||
@ -170,11 +176,11 @@ V:
|
|||||||
|
|
||||||
An incomplete list of some future Milestones is below:
|
An incomplete list of some future Milestones is below:
|
||||||
|
|
||||||
* First Y6 CopterControl flight
|
* First Helicopter flight with OpenPilot Pro
|
||||||
* First Helicopter flight with OpenPilot
|
* First fixed wing navigation flight on CopterControl
|
||||||
* First successful flight using the GCS only and no RC TX
|
* First successful flight using the GCS only and no RC TX
|
||||||
* First use of Magic Waypoint
|
* First use of Magic Waypoint
|
||||||
* First Flybarless Helicopter flight with OpenPilot
|
* First Flybarless Helicopter flight with OpenPilot Pro
|
||||||
* First fixed wing navigation flight
|
* First fixed wing navigation flight
|
||||||
* First Multirotor navigation flight
|
* First Multirotor navigation flight
|
||||||
* First Helicopter navigation flight
|
* First Helicopter navigation flight
|
||||||
@ -183,4 +189,3 @@ An incomplete list of some future Milestones is below:
|
|||||||
* First "Follow Me" navigation flight
|
* First "Follow Me" navigation flight
|
||||||
* First Channel Crossing with OpenPilot
|
* First Channel Crossing with OpenPilot
|
||||||
|
|
||||||
|
|
||||||
|
12
Makefile
12
Makefile
@ -183,13 +183,13 @@ qt_sdk_clean:
|
|||||||
ARM_SDK_DIR := $(TOOLS_DIR)/arm-2011.03
|
ARM_SDK_DIR := $(TOOLS_DIR)/arm-2011.03
|
||||||
|
|
||||||
.PHONY: arm_sdk_install
|
.PHONY: arm_sdk_install
|
||||||
arm_sdk_install: ARM_SDK_URL := http://www.codesourcery.com/sgpp/lite/arm/portal/package8734/public/arm-none-eabi/arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
|
arm_sdk_install: ARM_SDK_URL := https://sourcery.mentor.com/sgpp/lite/arm/portal/package8736/public/arm-none-eabi/arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
|
||||||
arm_sdk_install: ARM_SDK_FILE := $(notdir $(ARM_SDK_URL))
|
arm_sdk_install: ARM_SDK_FILE := $(notdir $(ARM_SDK_URL))
|
||||||
# order-only prereq on directory existance:
|
# order-only prereq on directory existance:
|
||||||
arm_sdk_install: | $(DL_DIR) $(TOOLS_DIR)
|
arm_sdk_install: | $(DL_DIR) $(TOOLS_DIR)
|
||||||
arm_sdk_install: arm_sdk_clean
|
arm_sdk_install: arm_sdk_clean
|
||||||
# download the source only if it's newer than what we already have
|
# download the source only if it's newer than what we already have
|
||||||
$(V1) wget -N -P "$(DL_DIR)" "$(ARM_SDK_URL)"
|
$(V1) wget --no-check-certificate -N -P "$(DL_DIR)" "$(ARM_SDK_URL)"
|
||||||
|
|
||||||
# binary only release so just extract it
|
# binary only release so just extract it
|
||||||
$(V1) tar -C $(TOOLS_DIR) -xjf "$(DL_DIR)/$(ARM_SDK_FILE)"
|
$(V1) tar -C $(TOOLS_DIR) -xjf "$(DL_DIR)/$(ARM_SDK_FILE)"
|
||||||
@ -202,8 +202,8 @@ arm_sdk_clean:
|
|||||||
OPENOCD_DIR := $(TOOLS_DIR)/openocd
|
OPENOCD_DIR := $(TOOLS_DIR)/openocd
|
||||||
|
|
||||||
.PHONY: openocd_install
|
.PHONY: openocd_install
|
||||||
openocd_install: OPENOCD_URL := http://sourceforge.net/projects/openocd/files/openocd/0.4.0/openocd-0.4.0.tar.bz2/download
|
openocd_install: OPENOCD_URL := http://sourceforge.net/projects/openocd/files/openocd/0.5.0/openocd-0.5.0.tar.bz2/download
|
||||||
openocd_install: OPENOCD_FILE := openocd-0.4.0.tar.bz2
|
openocd_install: OPENOCD_FILE := openocd-0.5.0.tar.bz2
|
||||||
# order-only prereq on directory existance:
|
# order-only prereq on directory existance:
|
||||||
openocd_install: | $(DL_DIR) $(TOOLS_DIR)
|
openocd_install: | $(DL_DIR) $(TOOLS_DIR)
|
||||||
openocd_install: openocd_clean
|
openocd_install: openocd_clean
|
||||||
@ -218,8 +218,8 @@ openocd_install: openocd_clean
|
|||||||
# build and install
|
# build and install
|
||||||
$(V1) mkdir -p "$(OPENOCD_DIR)"
|
$(V1) mkdir -p "$(OPENOCD_DIR)"
|
||||||
$(V1) ( \
|
$(V1) ( \
|
||||||
cd $(DL_DIR)/openocd-build/openocd-0.4.0 ; \
|
cd $(DL_DIR)/openocd-build/openocd-0.5.0 ; \
|
||||||
./configure --prefix="$(OPENOCD_DIR)" --enable-ft2232_libftdi ; \
|
./configure --prefix="$(OPENOCD_DIR)" --enable-ft2232_libftdi --enable-buspirate; \
|
||||||
$(MAKE) ; \
|
$(MAKE) ; \
|
||||||
$(MAKE) install ; \
|
$(MAKE) install ; \
|
||||||
)
|
)
|
||||||
|
Binary file not shown.
@ -355,7 +355,7 @@ $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin
|
|||||||
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
||||||
|
|
||||||
# Add jtag targets (program and wipe)
|
# Add jtag targets (program and wipe)
|
||||||
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE)))
|
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG)))
|
||||||
|
|
||||||
.PHONY: elf lss sym hex bin bino opfw
|
.PHONY: elf lss sym hex bin bino opfw
|
||||||
elf: $(OUTDIR)/$(TARGET).elf
|
elf: $(OUTDIR)/$(TARGET).elf
|
||||||
|
@ -258,7 +258,9 @@ CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
|||||||
|
|
||||||
CFLAGS += -mapcs-frame
|
CFLAGS += -mapcs-frame
|
||||||
CFLAGS += -fomit-frame-pointer
|
CFLAGS += -fomit-frame-pointer
|
||||||
|
ifeq ($(CODE_SOURCERY), YES)
|
||||||
CFLAGS += -fpromote-loop-indices
|
CFLAGS += -fpromote-loop-indices
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Werror
|
CFLAGS += -Werror
|
||||||
|
@ -300,7 +300,9 @@ CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
|||||||
|
|
||||||
CFLAGS += -mapcs-frame
|
CFLAGS += -mapcs-frame
|
||||||
CFLAGS += -fomit-frame-pointer
|
CFLAGS += -fomit-frame-pointer
|
||||||
|
ifeq ($(CODE_SOURCERY), YES)
|
||||||
CFLAGS += -fpromote-loop-indices
|
CFLAGS += -fpromote-loop-indices
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Werror
|
CFLAGS += -Werror
|
||||||
|
@ -306,7 +306,9 @@ CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
|||||||
|
|
||||||
CFLAGS += -mapcs-frame
|
CFLAGS += -mapcs-frame
|
||||||
CFLAGS += -fomit-frame-pointer
|
CFLAGS += -fomit-frame-pointer
|
||||||
|
ifeq ($(CODE_SOURCERY), YES)
|
||||||
CFLAGS += -fpromote-loop-indices
|
CFLAGS += -fpromote-loop-indices
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Werror
|
CFLAGS += -Werror
|
||||||
|
@ -301,7 +301,9 @@ CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
|||||||
|
|
||||||
CFLAGS += -mapcs-frame
|
CFLAGS += -mapcs-frame
|
||||||
CFLAGS += -fomit-frame-pointer
|
CFLAGS += -fomit-frame-pointer
|
||||||
|
ifeq ($(CODE_SOURCERY), YES)
|
||||||
CFLAGS += -fpromote-loop-indices
|
CFLAGS += -fpromote-loop-indices
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Werror
|
CFLAGS += -Werror
|
||||||
|
@ -65,7 +65,8 @@ endif
|
|||||||
FLASH_TOOL = OPENOCD
|
FLASH_TOOL = OPENOCD
|
||||||
|
|
||||||
# List of modules to include
|
# List of modules to include
|
||||||
OPTMODULES = CameraStab GPS
|
OPTMODULES = CameraStab
|
||||||
|
OPTMODULES += GPS
|
||||||
MODULES = Attitude Stabilization Actuator ManualControl FirmwareIAP
|
MODULES = Attitude Stabilization Actuator ManualControl FirmwareIAP
|
||||||
# Telemetry must be last to grab the optional modules (why?)
|
# Telemetry must be last to grab the optional modules (why?)
|
||||||
MODULES += Telemetry
|
MODULES += Telemetry
|
||||||
@ -170,7 +171,8 @@ SRC += $(OPUAVSYNTHDIR)/camerastabsettings.c
|
|||||||
SRC += $(OPUAVSYNTHDIR)/cameradesired.c
|
SRC += $(OPUAVSYNTHDIR)/cameradesired.c
|
||||||
SRC += $(OPUAVSYNTHDIR)/gpsposition.c
|
SRC += $(OPUAVSYNTHDIR)/gpsposition.c
|
||||||
SRC += $(OPUAVSYNTHDIR)/hwsettings.c
|
SRC += $(OPUAVSYNTHDIR)/hwsettings.c
|
||||||
|
SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c
|
||||||
|
SRC += $(OPUAVSYNTHDIR)/receiveractivity.c
|
||||||
SRC += $(OPUAVSYNTHDIR)/taskinfo.c
|
SRC += $(OPUAVSYNTHDIR)/taskinfo.c
|
||||||
SRC += $(OPUAVSYNTHDIR)/mixerstatus.c
|
SRC += $(OPUAVSYNTHDIR)/mixerstatus.c
|
||||||
SRC += $(OPUAVSYNTHDIR)/ratedesired.c
|
SRC += $(OPUAVSYNTHDIR)/ratedesired.c
|
||||||
@ -196,6 +198,7 @@ SRC += $(PIOSSTM32F10X)/pios_gpio.c
|
|||||||
SRC += $(PIOSSTM32F10X)/pios_exti.c
|
SRC += $(PIOSSTM32F10X)/pios_exti.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_rtc.c
|
SRC += $(PIOSSTM32F10X)/pios_rtc.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_wdg.c
|
SRC += $(PIOSSTM32F10X)/pios_wdg.c
|
||||||
|
SRC += $(PIOSSTM32F10X)/pios_tim.c
|
||||||
|
|
||||||
|
|
||||||
# PIOS USB related files (seperated to make code maintenance more easy)
|
# PIOS USB related files (seperated to make code maintenance more easy)
|
||||||
@ -214,6 +217,7 @@ SRC += $(PIOSCOMMON)/pios_i2c_esc.c
|
|||||||
SRC += $(PIOSCOMMON)/pios_iap.c
|
SRC += $(PIOSCOMMON)/pios_iap.c
|
||||||
SRC += $(PIOSCOMMON)/pios_bl_helper.c
|
SRC += $(PIOSCOMMON)/pios_bl_helper.c
|
||||||
SRC += $(PIOSCOMMON)/pios_rcvr.c
|
SRC += $(PIOSCOMMON)/pios_rcvr.c
|
||||||
|
SRC += $(PIOSCOMMON)/pios_gcsrcvr.c
|
||||||
SRC += $(PIOSCOMMON)/printf-stdarg.c
|
SRC += $(PIOSCOMMON)/printf-stdarg.c
|
||||||
## Libraries for flight calculations
|
## Libraries for flight calculations
|
||||||
SRC += $(FLIGHTLIB)/fifo_buffer.c
|
SRC += $(FLIGHTLIB)/fifo_buffer.c
|
||||||
@ -443,7 +447,9 @@ CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
|||||||
|
|
||||||
CFLAGS += -mapcs-frame
|
CFLAGS += -mapcs-frame
|
||||||
CFLAGS += -fomit-frame-pointer
|
CFLAGS += -fomit-frame-pointer
|
||||||
|
ifeq ($(CODE_SOURCERY), YES)
|
||||||
CFLAGS += -fpromote-loop-indices
|
CFLAGS += -fpromote-loop-indices
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Werror
|
CFLAGS += -Werror
|
||||||
@ -568,7 +574,7 @@ $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin
|
|||||||
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
||||||
|
|
||||||
# Add jtag targets (program and wipe)
|
# Add jtag targets (program and wipe)
|
||||||
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE)))
|
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG)))
|
||||||
|
|
||||||
.PHONY: elf lss sym hex bin bino opfw
|
.PHONY: elf lss sym hex bin bino opfw
|
||||||
elf: $(OUTDIR)/$(TARGET).elf
|
elf: $(OUTDIR)/$(TARGET).elf
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define configUSE_PREEMPTION 1
|
#define configUSE_PREEMPTION 1
|
||||||
#define configUSE_IDLE_HOOK 1
|
#define configUSE_IDLE_HOOK 1
|
||||||
#define configUSE_TICK_HOOK 0
|
#define configUSE_TICK_HOOK 0
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
|
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
|
||||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||||
|
@ -48,8 +48,9 @@
|
|||||||
/* Supported receiver interfaces */
|
/* Supported receiver interfaces */
|
||||||
#define PIOS_INCLUDE_SPEKTRUM
|
#define PIOS_INCLUDE_SPEKTRUM
|
||||||
#define PIOS_INCLUDE_SBUS
|
#define PIOS_INCLUDE_SBUS
|
||||||
//#define PIOS_INCLUDE_PPM
|
#define PIOS_INCLUDE_PPM
|
||||||
#define PIOS_INCLUDE_PWM
|
#define PIOS_INCLUDE_PWM
|
||||||
|
#define PIOS_INCLUDE_GCSRCVR
|
||||||
|
|
||||||
/* Supported USART-based PIOS modules */
|
/* Supported USART-based PIOS modules */
|
||||||
#define PIOS_INCLUDE_TELEMETRY_RF
|
#define PIOS_INCLUDE_TELEMETRY_RF
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <uavobjectsinit.h>
|
#include <uavobjectsinit.h>
|
||||||
#include <hwsettings.h>
|
#include <hwsettings.h>
|
||||||
#include <manualcontrolsettings.h>
|
#include <manualcontrolsettings.h>
|
||||||
|
#include <gcsreceiver.h>
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_SPI)
|
#if defined(PIOS_INCLUDE_SPI)
|
||||||
|
|
||||||
@ -195,6 +196,220 @@ void PIOS_ADC_handler() {
|
|||||||
PIOS_ADC_DMA_Handler();
|
PIOS_ADC_DMA_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "pios_tim_priv.h"
|
||||||
|
|
||||||
|
static const TIM_TimeBaseInitTypeDef tim_1_2_3_4_time_base = {
|
||||||
|
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
||||||
|
.TIM_ClockDivision = TIM_CKD_DIV1,
|
||||||
|
.TIM_CounterMode = TIM_CounterMode_Up,
|
||||||
|
.TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1),
|
||||||
|
.TIM_RepetitionCounter = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_1_cfg = {
|
||||||
|
.timer = TIM1,
|
||||||
|
.time_base_init = &tim_1_2_3_4_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM1_CC_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_2_cfg = {
|
||||||
|
.timer = TIM2,
|
||||||
|
.time_base_init = &tim_1_2_3_4_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM2_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_3_cfg = {
|
||||||
|
.timer = TIM3,
|
||||||
|
.time_base_init = &tim_1_2_3_4_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM3_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_4_cfg = {
|
||||||
|
.timer = TIM4,
|
||||||
|
.time_base_init = &tim_1_2_3_4_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM4_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = {
|
||||||
|
{
|
||||||
|
.timer = TIM4,
|
||||||
|
.timer_chan = TIM_Channel_1,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_6,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM3,
|
||||||
|
.timer_chan = TIM_Channel_2,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_5,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.remap = GPIO_PartialRemap_TIM3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM3,
|
||||||
|
.timer_chan = TIM_Channel_3,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_0,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM3,
|
||||||
|
.timer_chan = TIM_Channel_4,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_1,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM2,
|
||||||
|
.timer_chan = TIM_Channel_1,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOA,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_0,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM2,
|
||||||
|
.timer_chan = TIM_Channel_2,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOA,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_1,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_channel pios_tim_servoport_all_pins[] = {
|
||||||
|
{
|
||||||
|
.timer = TIM4,
|
||||||
|
.timer_chan = TIM_Channel_4,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_9,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM4,
|
||||||
|
.timer_chan = TIM_Channel_3,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_8,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM4,
|
||||||
|
.timer_chan = TIM_Channel_2,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_7,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM1,
|
||||||
|
.timer_chan = TIM_Channel_1,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOA,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_8,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM3,
|
||||||
|
.timer_chan = TIM_Channel_1,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_4,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.remap = GPIO_PartialRemap_TIM3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.timer = TIM2,
|
||||||
|
.timer_chan = TIM_Channel_3,
|
||||||
|
.pin = {
|
||||||
|
.gpio = GPIOA,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_2,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_USART)
|
#if defined(PIOS_INCLUDE_USART)
|
||||||
|
|
||||||
#include "pios_usart_priv.h"
|
#include "pios_usart_priv.h"
|
||||||
@ -564,121 +779,40 @@ void PIOS_RTC_IRQ_Handler (void)
|
|||||||
* Servo outputs
|
* Servo outputs
|
||||||
*/
|
*/
|
||||||
#include <pios_servo_priv.h>
|
#include <pios_servo_priv.h>
|
||||||
static const struct pios_servo_channel pios_servo_channels[] = {
|
|
||||||
{
|
|
||||||
.timer = TIM4,
|
|
||||||
.port = GPIOB,
|
|
||||||
.channel = TIM_Channel_4,
|
|
||||||
.pin = GPIO_Pin_9,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM4,
|
|
||||||
.port = GPIOB,
|
|
||||||
.channel = TIM_Channel_3,
|
|
||||||
.pin = GPIO_Pin_8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM4,
|
|
||||||
.port = GPIOB,
|
|
||||||
.channel = TIM_Channel_2,
|
|
||||||
.pin = GPIO_Pin_7,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM1,
|
|
||||||
.port = GPIOA,
|
|
||||||
.channel = TIM_Channel_1,
|
|
||||||
.pin = GPIO_Pin_8,
|
|
||||||
},
|
|
||||||
{ /* needs to remap to alternative function */
|
|
||||||
.timer = TIM3,
|
|
||||||
.port = GPIOB,
|
|
||||||
.channel = TIM_Channel_1,
|
|
||||||
.pin = GPIO_Pin_4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM2,
|
|
||||||
.port = GPIOA,
|
|
||||||
.channel = TIM_Channel_3,
|
|
||||||
.pin = GPIO_Pin_2,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct pios_servo_cfg pios_servo_cfg = {
|
const struct pios_servo_cfg pios_servo_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1),
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_oc_init = {
|
.tim_oc_init = {
|
||||||
.TIM_OCMode = TIM_OCMode_PWM1,
|
.TIM_OCMode = TIM_OCMode_PWM1,
|
||||||
.TIM_OutputState = TIM_OutputState_Enable,
|
.TIM_OutputState = TIM_OutputState_Enable,
|
||||||
.TIM_OutputNState = TIM_OutputNState_Disable,
|
.TIM_OutputNState = TIM_OutputNState_Disable,
|
||||||
.TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION,
|
.TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION,
|
||||||
.TIM_OCPolarity = TIM_OCPolarity_High,
|
.TIM_OCPolarity = TIM_OCPolarity_High,
|
||||||
.TIM_OCNPolarity = TIM_OCPolarity_High,
|
.TIM_OCNPolarity = TIM_OCPolarity_High,
|
||||||
.TIM_OCIdleState = TIM_OCIdleState_Reset,
|
.TIM_OCIdleState = TIM_OCIdleState_Reset,
|
||||||
.TIM_OCNIdleState = TIM_OCNIdleState_Reset,
|
.TIM_OCNIdleState = TIM_OCNIdleState_Reset,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
.channels = pios_tim_servoport_all_pins,
|
||||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
.num_channels = NELEMENTS(pios_tim_servoport_all_pins),
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
|
||||||
},
|
|
||||||
.remap = GPIO_PartialRemap_TIM3,
|
|
||||||
.channels = pios_servo_channels,
|
|
||||||
.num_channels = NELEMENTS(pios_servo_channels),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_PWM) && defined(PIOS_INCLUDE_PPM)
|
|
||||||
#error Cannot define both PIOS_INCLUDE_PWM and PIOS_INCLUDE_PPM at the same time (yet)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PPM Inputs
|
* PPM Inputs
|
||||||
*/
|
*/
|
||||||
#if defined(PIOS_INCLUDE_PPM)
|
#if defined(PIOS_INCLUDE_PPM)
|
||||||
#include <pios_ppm_priv.h>
|
#include <pios_ppm_priv.h>
|
||||||
|
|
||||||
void TIM4_IRQHandler();
|
|
||||||
void TIM4_IRQHandler() __attribute__ ((alias ("PIOS_TIM4_irq_handler")));
|
|
||||||
const struct pios_ppm_cfg pios_ppm_cfg = {
|
const struct pios_ppm_cfg pios_ppm_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, /* For 1 uS accuracy */
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = 0xFFFF, /* shared timer, make sure init correctly in outputs */
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_ic_init = {
|
.tim_ic_init = {
|
||||||
.TIM_Channel = TIM_Channel_1,
|
|
||||||
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
||||||
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
||||||
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
||||||
.TIM_ICFilter = 0x0,
|
.TIM_ICFilter = 0x0,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
/* Use only the first channel for ppm */
|
||||||
.GPIO_Pin = GPIO_Pin_6,
|
.channels = &pios_tim_rcvrport_all_channels[0],
|
||||||
.GPIO_Mode = GPIO_Mode_IPD,
|
.num_channels = 1,
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
|
||||||
},
|
|
||||||
.remap = 0,
|
|
||||||
.irq = {
|
|
||||||
.init = {
|
|
||||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
|
||||||
.NVIC_IRQChannelSubPriority = 0,
|
|
||||||
.NVIC_IRQChannelCmd = ENABLE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.timer = TIM4,
|
|
||||||
.port = GPIOB,
|
|
||||||
.ccr = TIM_IT_CC1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void PIOS_TIM4_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PPM_irq_handler();
|
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_PPM */
|
#endif /* PIOS_INCLUDE_PPM */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -687,98 +821,16 @@ void PIOS_TIM4_irq_handler()
|
|||||||
#if defined(PIOS_INCLUDE_PWM)
|
#if defined(PIOS_INCLUDE_PWM)
|
||||||
#include <pios_pwm_priv.h>
|
#include <pios_pwm_priv.h>
|
||||||
|
|
||||||
static const struct pios_pwm_channel pios_pwm_channels[] = {
|
|
||||||
{
|
|
||||||
.timer = TIM4,
|
|
||||||
.port = GPIOB,
|
|
||||||
.ccr = TIM_IT_CC1,
|
|
||||||
.channel = TIM_Channel_1,
|
|
||||||
.pin = GPIO_Pin_6,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM3,
|
|
||||||
.port = GPIOB,
|
|
||||||
.ccr = TIM_IT_CC2,
|
|
||||||
.channel = TIM_Channel_2,
|
|
||||||
.pin = GPIO_Pin_5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM3,
|
|
||||||
.port = GPIOB,
|
|
||||||
.ccr = TIM_IT_CC3,
|
|
||||||
.channel = TIM_Channel_3,
|
|
||||||
.pin = GPIO_Pin_0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM3,
|
|
||||||
.port = GPIOB,
|
|
||||||
.ccr = TIM_IT_CC4,
|
|
||||||
.channel = TIM_Channel_4,
|
|
||||||
.pin = GPIO_Pin_1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM2,
|
|
||||||
.port = GPIOA,
|
|
||||||
.ccr = TIM_IT_CC1,
|
|
||||||
.channel = TIM_Channel_1,
|
|
||||||
.pin = GPIO_Pin_0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.timer = TIM2,
|
|
||||||
.port = GPIOA,
|
|
||||||
.ccr = TIM_IT_CC2,
|
|
||||||
.channel = TIM_Channel_2,
|
|
||||||
.pin = GPIO_Pin_1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
void TIM2_IRQHandler();
|
|
||||||
void TIM3_IRQHandler();
|
|
||||||
void TIM4_IRQHandler();
|
|
||||||
void TIM2_IRQHandler() __attribute__ ((alias ("PIOS_TIM2_irq_handler")));
|
|
||||||
void TIM3_IRQHandler() __attribute__ ((alias ("PIOS_TIM3_irq_handler")));
|
|
||||||
void TIM4_IRQHandler() __attribute__ ((alias ("PIOS_TIM4_irq_handler")));
|
|
||||||
const struct pios_pwm_cfg pios_pwm_cfg = {
|
const struct pios_pwm_cfg pios_pwm_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = 0xFFFF,
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_ic_init = {
|
.tim_ic_init = {
|
||||||
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
||||||
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
||||||
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
||||||
.TIM_ICFilter = 0x0,
|
.TIM_ICFilter = 0x0,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
.channels = pios_tim_rcvrport_all_channels,
|
||||||
.GPIO_Mode = GPIO_Mode_IPD,
|
.num_channels = NELEMENTS(pios_tim_rcvrport_all_channels),
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
|
||||||
},
|
|
||||||
.remap = 0,
|
|
||||||
.irq = {
|
|
||||||
.init = {
|
|
||||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
|
||||||
.NVIC_IRQChannelSubPriority = 0,
|
|
||||||
.NVIC_IRQChannelCmd = ENABLE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.channels = pios_pwm_channels,
|
|
||||||
.num_channels = NELEMENTS(pios_pwm_channels),
|
|
||||||
};
|
};
|
||||||
void PIOS_TIM2_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM2);
|
|
||||||
}
|
|
||||||
void PIOS_TIM3_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM3);
|
|
||||||
}
|
|
||||||
void PIOS_TIM4_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM4);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_I2C)
|
#if defined(PIOS_INCLUDE_I2C)
|
||||||
@ -856,11 +908,19 @@ void PIOS_I2C_main_adapter_er_irq_handler(void)
|
|||||||
|
|
||||||
#endif /* PIOS_INCLUDE_I2C */
|
#endif /* PIOS_INCLUDE_I2C */
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_GCSRCVR)
|
||||||
|
#include "pios_gcsrcvr_priv.h"
|
||||||
|
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_RCVR)
|
#if defined(PIOS_INCLUDE_RCVR)
|
||||||
#include "pios_rcvr_priv.h"
|
#include "pios_rcvr_priv.h"
|
||||||
|
|
||||||
struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[PIOS_RCVR_MAX_CHANNELS];
|
/* One slot per selectable receiver group.
|
||||||
uint32_t pios_rcvr_max_channel;
|
* eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS
|
||||||
|
* NOTE: No slot in this map for NONE.
|
||||||
|
*/
|
||||||
|
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];
|
||||||
|
|
||||||
#endif /* PIOS_INCLUDE_RCVR */
|
#endif /* PIOS_INCLUDE_RCVR */
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_USB_HID)
|
#if defined(PIOS_INCLUDE_USB_HID)
|
||||||
@ -909,7 +969,6 @@ void PIOS_Board_Init(void) {
|
|||||||
UAVObjInitialize();
|
UAVObjInitialize();
|
||||||
|
|
||||||
HwSettingsInitialize();
|
HwSettingsInitialize();
|
||||||
ManualControlSettingsInitialize();
|
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_RTC)
|
#if defined(PIOS_INCLUDE_RTC)
|
||||||
/* Initialize the real-time clock and its associated tick */
|
/* Initialize the real-time clock and its associated tick */
|
||||||
@ -922,6 +981,12 @@ void PIOS_Board_Init(void) {
|
|||||||
/* Initialize the task monitor library */
|
/* Initialize the task monitor library */
|
||||||
TaskMonitorInitialize();
|
TaskMonitorInitialize();
|
||||||
|
|
||||||
|
/* Set up pulse timers */
|
||||||
|
PIOS_TIM_InitClock(&tim_1_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_2_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_3_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_4_cfg);
|
||||||
|
|
||||||
/* Configure the main IO port */
|
/* Configure the main IO port */
|
||||||
uint8_t hwsettings_DSMxBind;
|
uint8_t hwsettings_DSMxBind;
|
||||||
HwSettingsDSMxBindGet(&hwsettings_DSMxBind);
|
HwSettingsDSMxBindGet(&hwsettings_DSMxBind);
|
||||||
@ -963,6 +1028,13 @@ void PIOS_Board_Init(void) {
|
|||||||
if (PIOS_SBUS_Init(&pios_sbus_id, &pios_sbus_cfg, &pios_usart_com_driver, pios_usart_sbus_id)) {
|
if (PIOS_SBUS_Init(&pios_sbus_id, &pios_sbus_cfg, &pios_usart_com_driver, pios_usart_sbus_id)) {
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pios_sbus_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_sbus_rcvr_id, &pios_sbus_rcvr_driver, pios_sbus_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SBUS] = pios_sbus_rcvr_id;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_SBUS */
|
#endif /* PIOS_INCLUDE_SBUS */
|
||||||
break;
|
break;
|
||||||
@ -984,7 +1056,8 @@ void PIOS_Board_Init(void) {
|
|||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_GPS */
|
#endif /* PIOS_INCLUDE_GPS */
|
||||||
break;
|
break;
|
||||||
case HWSETTINGS_CC_MAINPORT_SPEKTRUM:
|
case HWSETTINGS_CC_MAINPORT_SPEKTRUM1:
|
||||||
|
case HWSETTINGS_CC_MAINPORT_SPEKTRUM2:
|
||||||
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
||||||
{
|
{
|
||||||
uint32_t pios_usart_spektrum_id;
|
uint32_t pios_usart_spektrum_id;
|
||||||
@ -996,6 +1069,16 @@ void PIOS_Board_Init(void) {
|
|||||||
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_main_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, 0)) {
|
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_main_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, 0)) {
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pios_spektrum_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, pios_spektrum_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
if (hwsettings_cc_mainport == HWSETTINGS_CC_MAINPORT_SPEKTRUM1) {
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1] = pios_spektrum_rcvr_id;
|
||||||
|
} else {
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM2] = pios_spektrum_rcvr_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_SPEKTRUM */
|
#endif /* PIOS_INCLUDE_SPEKTRUM */
|
||||||
break;
|
break;
|
||||||
@ -1046,7 +1129,8 @@ void PIOS_Board_Init(void) {
|
|||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_GPS */
|
#endif /* PIOS_INCLUDE_GPS */
|
||||||
break;
|
break;
|
||||||
case HWSETTINGS_CC_FLEXIPORT_SPEKTRUM:
|
case HWSETTINGS_CC_FLEXIPORT_SPEKTRUM1:
|
||||||
|
case HWSETTINGS_CC_FLEXIPORT_SPEKTRUM2:
|
||||||
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
||||||
{
|
{
|
||||||
uint32_t pios_usart_spektrum_id;
|
uint32_t pios_usart_spektrum_id;
|
||||||
@ -1058,6 +1142,16 @@ void PIOS_Board_Init(void) {
|
|||||||
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_flexi_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, hwsettings_DSMxBind)) {
|
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_flexi_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, hwsettings_DSMxBind)) {
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pios_spektrum_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, pios_spektrum_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
if (hwsettings_cc_flexiport == HWSETTINGS_CC_FLEXIPORT_SPEKTRUM1) {
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1] = pios_spektrum_rcvr_id;
|
||||||
|
} else {
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM2] = pios_spektrum_rcvr_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_SPEKTRUM */
|
#endif /* PIOS_INCLUDE_SPEKTRUM */
|
||||||
break;
|
break;
|
||||||
@ -1074,83 +1168,61 @@ void PIOS_Board_Init(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the selected receiver */
|
/* Configure the rcvr port */
|
||||||
uint8_t manualcontrolsettings_inputmode;
|
uint8_t hwsettings_rcvrport;
|
||||||
ManualControlSettingsInputModeGet(&manualcontrolsettings_inputmode);
|
HwSettingsCC_RcvrPortGet(&hwsettings_rcvrport);
|
||||||
|
|
||||||
switch (manualcontrolsettings_inputmode) {
|
switch (hwsettings_rcvrport) {
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_PWM:
|
case HWSETTINGS_CC_RCVRPORT_DISABLED:
|
||||||
|
break;
|
||||||
|
case HWSETTINGS_CC_RCVRPORT_PWM:
|
||||||
#if defined(PIOS_INCLUDE_PWM)
|
#if defined(PIOS_INCLUDE_PWM)
|
||||||
PIOS_PWM_Init();
|
{
|
||||||
uint32_t pios_pwm_rcvr_id;
|
uint32_t pios_pwm_id;
|
||||||
if (PIOS_RCVR_Init(&pios_pwm_rcvr_id, &pios_pwm_rcvr_driver, 0)) {
|
PIOS_PWM_Init(&pios_pwm_id, &pios_pwm_cfg);
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
uint32_t pios_pwm_rcvr_id;
|
||||||
for (uint8_t i = 0;
|
if (PIOS_RCVR_Init(&pios_pwm_rcvr_id, &pios_pwm_rcvr_driver, pios_pwm_id)) {
|
||||||
i < PIOS_PWM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
PIOS_Assert(0);
|
||||||
i++) {
|
}
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_pwm_rcvr_id;
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_PWM] = pios_pwm_rcvr_id;
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_PWM */
|
#endif /* PIOS_INCLUDE_PWM */
|
||||||
break;
|
break;
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_PPM:
|
case HWSETTINGS_CC_RCVRPORT_PPM:
|
||||||
#if defined(PIOS_INCLUDE_PPM)
|
#if defined(PIOS_INCLUDE_PPM)
|
||||||
PIOS_PPM_Init();
|
{
|
||||||
uint32_t pios_ppm_rcvr_id;
|
uint32_t pios_ppm_id;
|
||||||
if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, 0)) {
|
PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_cfg);
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
uint32_t pios_ppm_rcvr_id;
|
||||||
for (uint8_t i = 0;
|
if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, pios_ppm_id)) {
|
||||||
i < PIOS_PPM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
PIOS_Assert(0);
|
||||||
i++) {
|
}
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_ppm_rcvr_id;
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_PPM] = pios_ppm_rcvr_id;
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_PPM */
|
#endif /* PIOS_INCLUDE_PPM */
|
||||||
break;
|
break;
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_SPEKTRUM:
|
|
||||||
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
|
||||||
if (hwsettings_cc_mainport == HWSETTINGS_CC_MAINPORT_SPEKTRUM ||
|
|
||||||
hwsettings_cc_flexiport == HWSETTINGS_CC_FLEXIPORT_SPEKTRUM) {
|
|
||||||
uint32_t pios_spektrum_rcvr_id;
|
|
||||||
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < PIOS_SPEKTRUM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
|
||||||
i++) {
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_spektrum_rcvr_id;
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_SPEKTRUM */
|
|
||||||
break;
|
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_SBUS:
|
|
||||||
#if defined(PIOS_INCLUDE_SBUS)
|
|
||||||
if (hwsettings_cc_mainport == HWSETTINGS_CC_MAINPORT_SBUS) {
|
|
||||||
uint32_t pios_sbus_rcvr_id;
|
|
||||||
if (PIOS_RCVR_Init(&pios_sbus_rcvr_id, &pios_sbus_rcvr_driver, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < SBUS_NUMBER_OF_CHANNELS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
|
||||||
i++) {
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_sbus_rcvr_id;
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_SBUS */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_GCSRCVR)
|
||||||
|
GCSReceiverInitialize();
|
||||||
|
PIOS_GCSRCVR_Init();
|
||||||
|
uint32_t pios_gcsrcvr_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_gcsrcvr_rcvr_id, &pios_gcsrcvr_rcvr_driver, 0)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_GCS] = pios_gcsrcvr_rcvr_id;
|
||||||
|
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||||
|
|
||||||
/* Remap AFIO pin */
|
/* Remap AFIO pin */
|
||||||
GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE);
|
GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE);
|
||||||
PIOS_Servo_Init();
|
|
||||||
|
#ifndef PIOS_DEBUG_ENABLE_DEBUG_PINS
|
||||||
|
PIOS_Servo_Init(&pios_servo_cfg);
|
||||||
|
#else
|
||||||
|
PIOS_DEBUG_Init(&pios_tim_servo_all_channels, NELEMENTS(pios_tim_servo_all_channels));
|
||||||
|
#endif /* PIOS_DEBUG_ENABLE_DEBUG_PINS */
|
||||||
|
|
||||||
PIOS_ADC_Init();
|
PIOS_ADC_Init();
|
||||||
PIOS_GPIO_Init();
|
PIOS_GPIO_Init();
|
||||||
|
@ -363,7 +363,7 @@ $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin
|
|||||||
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
||||||
|
|
||||||
# Add jtag targets (program and wipe)
|
# Add jtag targets (program and wipe)
|
||||||
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE)))
|
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG)))
|
||||||
|
|
||||||
.PHONY: elf lss sym hex bin bino opfw
|
.PHONY: elf lss sym hex bin bino opfw
|
||||||
elf: $(OUTDIR)/$(TARGET).elf
|
elf: $(OUTDIR)/$(TARGET).elf
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "pios.h"
|
||||||
#include "ahrs_spi_comm.h"
|
#include "ahrs_spi_comm.h"
|
||||||
#include "pios_debug.h"
|
#include "pios_debug.h"
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include "mixersettings.h"
|
#include "mixersettings.h"
|
||||||
#include "mixerstatus.h"
|
#include "mixerstatus.h"
|
||||||
#include "cameradesired.h"
|
#include "cameradesired.h"
|
||||||
|
#include "manualcontrolcommand.h"
|
||||||
|
|
||||||
// Private constants
|
// Private constants
|
||||||
#define MAX_QUEUE_SIZE 2
|
#define MAX_QUEUE_SIZE 2
|
||||||
@ -74,7 +74,7 @@ static void actuatorTask(void* parameters);
|
|||||||
static void actuator_update_rate(UAVObjEvent *);
|
static void actuator_update_rate(UAVObjEvent *);
|
||||||
static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral);
|
static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral);
|
||||||
static void setFailsafe();
|
static void setFailsafe();
|
||||||
static float MixerCurve(const float throttle, const float* curve);
|
static float MixerCurve(const float throttle, const float* curve, uint8_t elements);
|
||||||
static bool set_channel(uint8_t mixer_channel, uint16_t value);
|
static bool set_channel(uint8_t mixer_channel, uint16_t value);
|
||||||
float ProcessMixer(const int index, const float curve1, const float curve2,
|
float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||||
MixerSettingsData* mixerSettings, ActuatorDesiredData* desired,
|
MixerSettingsData* mixerSettings, ActuatorDesiredData* desired,
|
||||||
@ -219,22 +219,29 @@ static void actuatorTask(void* parameters)
|
|||||||
bool positiveThrottle = desired.Throttle >= 0.00;
|
bool positiveThrottle = desired.Throttle >= 0.00;
|
||||||
bool spinWhileArmed = MotorsSpinWhileArmed == ACTUATORSETTINGS_MOTORSSPINWHILEARMED_TRUE;
|
bool spinWhileArmed = MotorsSpinWhileArmed == ACTUATORSETTINGS_MOTORSSPINWHILEARMED_TRUE;
|
||||||
|
|
||||||
float curve1 = MixerCurve(desired.Throttle,mixerSettings.ThrottleCurve1);
|
float curve1 = MixerCurve(desired.Throttle,mixerSettings.ThrottleCurve1,MIXERSETTINGS_THROTTLECURVE1_NUMELEM);
|
||||||
|
|
||||||
//The source for the secondary curve is selectable
|
//The source for the secondary curve is selectable
|
||||||
float curve2 = 0;
|
float curve2 = 0;
|
||||||
AccessoryDesiredData accessory;
|
AccessoryDesiredData accessory;
|
||||||
switch(mixerSettings.Curve2Source) {
|
switch(mixerSettings.Curve2Source) {
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_THROTTLE:
|
case MIXERSETTINGS_CURVE2SOURCE_THROTTLE:
|
||||||
curve2 = MixerCurve(desired.Throttle,mixerSettings.ThrottleCurve2);
|
curve2 = MixerCurve(desired.Throttle,mixerSettings.ThrottleCurve2,MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
break;
|
break;
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_ROLL:
|
case MIXERSETTINGS_CURVE2SOURCE_ROLL:
|
||||||
curve2 = MixerCurve(desired.Roll,mixerSettings.ThrottleCurve2);
|
curve2 = MixerCurve(desired.Roll,mixerSettings.ThrottleCurve2,MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
break;
|
break;
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_PITCH:
|
case MIXERSETTINGS_CURVE2SOURCE_PITCH:
|
||||||
curve2 = MixerCurve(desired.Pitch,mixerSettings.ThrottleCurve2);
|
curve2 = MixerCurve(desired.Pitch,mixerSettings.ThrottleCurve2,
|
||||||
|
MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
break;
|
break;
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_YAW:
|
case MIXERSETTINGS_CURVE2SOURCE_YAW:
|
||||||
curve2 = MixerCurve(desired.Yaw,mixerSettings.ThrottleCurve2);
|
curve2 = MixerCurve(desired.Yaw,mixerSettings.ThrottleCurve2,MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
|
break;
|
||||||
|
case MIXERSETTINGS_CURVE2SOURCE_COLLECTIVE:
|
||||||
|
ManualControlCommandCollectiveGet(&curve2);
|
||||||
|
curve2 = MixerCurve(curve2,mixerSettings.ThrottleCurve2,
|
||||||
|
MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
break;
|
break;
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0:
|
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0:
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY1:
|
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY1:
|
||||||
@ -243,7 +250,7 @@ static void actuatorTask(void* parameters)
|
|||||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY4:
|
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY4:
|
||||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY5:
|
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY5:
|
||||||
if(AccessoryDesiredInstGet(mixerSettings.Curve2Source - MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0,&accessory) == 0)
|
if(AccessoryDesiredInstGet(mixerSettings.Curve2Source - MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0,&accessory) == 0)
|
||||||
curve2 = MixerCurve(accessory.AccessoryVal,mixerSettings.ThrottleCurve2);
|
curve2 = MixerCurve(accessory.AccessoryVal,mixerSettings.ThrottleCurve2,MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||||
else
|
else
|
||||||
curve2 = 0;
|
curve2 = 0;
|
||||||
break;
|
break;
|
||||||
@ -423,12 +430,9 @@ float ProcessMixer(const int index, const float curve1, const float curve2,
|
|||||||
*Interpolate a throttle curve. Throttle input should be in the range 0 to 1.
|
*Interpolate a throttle curve. Throttle input should be in the range 0 to 1.
|
||||||
*Output is in the range 0 to 1.
|
*Output is in the range 0 to 1.
|
||||||
*/
|
*/
|
||||||
|
static float MixerCurve(const float throttle, const float* curve, uint8_t elements)
|
||||||
#define MIXER_CURVE_ENTRIES 5
|
|
||||||
|
|
||||||
static float MixerCurve(const float throttle, const float* curve)
|
|
||||||
{
|
{
|
||||||
float scale = throttle * MIXER_CURVE_ENTRIES;
|
float scale = throttle * (elements - 1);
|
||||||
int idx1 = scale;
|
int idx1 = scale;
|
||||||
scale -= (float)idx1; //remainder
|
scale -= (float)idx1; //remainder
|
||||||
if(curve[0] < -1)
|
if(curve[0] < -1)
|
||||||
@ -441,12 +445,12 @@ static float MixerCurve(const float throttle, const float* curve)
|
|||||||
scale = 0;
|
scale = 0;
|
||||||
}
|
}
|
||||||
int idx2 = idx1 + 1;
|
int idx2 = idx1 + 1;
|
||||||
if(idx2 >= MIXER_CURVE_ENTRIES)
|
if(idx2 >= elements)
|
||||||
{
|
{
|
||||||
idx2 = MIXER_CURVE_ENTRIES -1; //clamp to highest entry in table
|
idx2 = elements -1; //clamp to highest entry in table
|
||||||
if(idx1 >= MIXER_CURVE_ENTRIES)
|
if(idx1 >= elements)
|
||||||
{
|
{
|
||||||
idx1 = MIXER_CURVE_ENTRIES -1;
|
idx1 = elements -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return((curve[idx1] * (1 - scale)) + (curve[idx2] * scale));
|
return((curve[idx1] * (1 - scale)) + (curve[idx2] * scale));
|
||||||
|
@ -105,4 +105,11 @@ int32_t ManualControlInitialize();
|
|||||||
( (int)MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_POSITIONHOLD == (int) FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD) \
|
( (int)MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_POSITIONHOLD == (int) FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define assumptions_channelcount ( \
|
||||||
|
( (int)MANUALCONTROLCOMMAND_CHANNEL_NUMELEM == (int)MANUALCONTROLSETTINGS_CHANNELGROUPS_NUMELEM ) && \
|
||||||
|
( (int)MANUALCONTROLCOMMAND_CHANNEL_NUMELEM == (int)MANUALCONTROLSETTINGS_CHANNELNUMBER_NUMELEM ) && \
|
||||||
|
( (int)MANUALCONTROLCOMMAND_CHANNEL_NUMELEM == (int)MANUALCONTROLSETTINGS_CHANNELMIN_NUMELEM ) && \
|
||||||
|
( (int)MANUALCONTROLCOMMAND_CHANNEL_NUMELEM == (int)MANUALCONTROLSETTINGS_CHANNELMAX_NUMELEM ) && \
|
||||||
|
( (int)MANUALCONTROLCOMMAND_CHANNEL_NUMELEM == (int)MANUALCONTROLSETTINGS_CHANNELNEUTRAL_NUMELEM ) )
|
||||||
|
|
||||||
#endif // MANUALCONTROL_H
|
#endif // MANUALCONTROL_H
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "flighttelemetrystats.h"
|
#include "flighttelemetrystats.h"
|
||||||
#include "flightstatus.h"
|
#include "flightstatus.h"
|
||||||
#include "accessorydesired.h"
|
#include "accessorydesired.h"
|
||||||
|
#include "receiveractivity.h"
|
||||||
|
|
||||||
// Private constants
|
// Private constants
|
||||||
#if defined(PIOS_MANUAL_STACK_SIZE)
|
#if defined(PIOS_MANUAL_STACK_SIZE)
|
||||||
@ -80,6 +81,7 @@ static void updateActuatorDesired(ManualControlCommandData * cmd);
|
|||||||
static void updateStabilizationDesired(ManualControlCommandData * cmd, ManualControlSettingsData * settings);
|
static void updateStabilizationDesired(ManualControlCommandData * cmd, ManualControlSettingsData * settings);
|
||||||
static void processFlightMode(ManualControlSettingsData * settings, float flightMode);
|
static void processFlightMode(ManualControlSettingsData * settings, float flightMode);
|
||||||
static void processArm(ManualControlCommandData * cmd, ManualControlSettingsData * settings);
|
static void processArm(ManualControlCommandData * cmd, ManualControlSettingsData * settings);
|
||||||
|
static void setArmedIfChanged(uint8_t val);
|
||||||
|
|
||||||
static void manualControlTask(void *parameters);
|
static void manualControlTask(void *parameters);
|
||||||
static float scaleChannel(int16_t value, int16_t max, int16_t min, int16_t neutral);
|
static float scaleChannel(int16_t value, int16_t max, int16_t min, int16_t neutral);
|
||||||
@ -87,7 +89,19 @@ static uint32_t timeDifferenceMs(portTickType start_time, portTickType end_time)
|
|||||||
static bool okToArm(void);
|
static bool okToArm(void);
|
||||||
static bool validInputRange(int16_t min, int16_t max, uint16_t value);
|
static bool validInputRange(int16_t min, int16_t max, uint16_t value);
|
||||||
|
|
||||||
#define assumptions (assumptions1 && assumptions3 && assumptions5 && assumptions7 && assumptions8 && assumptions_flightmode)
|
#define RCVR_ACTIVITY_MONITOR_CHANNELS_PER_GROUP 12
|
||||||
|
#define RCVR_ACTIVITY_MONITOR_MIN_RANGE 10
|
||||||
|
struct rcvr_activity_fsm {
|
||||||
|
ManualControlSettingsChannelGroupsOptions group;
|
||||||
|
uint16_t prev[RCVR_ACTIVITY_MONITOR_CHANNELS_PER_GROUP];
|
||||||
|
uint8_t sample_count;
|
||||||
|
};
|
||||||
|
static struct rcvr_activity_fsm activity_fsm;
|
||||||
|
|
||||||
|
static void resetRcvrActivity(struct rcvr_activity_fsm * fsm);
|
||||||
|
static bool updateRcvrActivity(struct rcvr_activity_fsm * fsm);
|
||||||
|
|
||||||
|
#define assumptions (assumptions1 && assumptions3 && assumptions5 && assumptions7 && assumptions8 && assumptions_flightmode && assumptions_channelcount)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module starting
|
* Module starting
|
||||||
@ -116,7 +130,7 @@ int32_t ManualControlInitialize()
|
|||||||
ManualControlCommandInitialize();
|
ManualControlCommandInitialize();
|
||||||
FlightStatusInitialize();
|
FlightStatusInitialize();
|
||||||
StabilizationDesiredInitialize();
|
StabilizationDesiredInitialize();
|
||||||
|
ReceiverActivityInitialize();
|
||||||
ManualControlSettingsInitialize();
|
ManualControlSettingsInitialize();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -147,10 +161,14 @@ static void manualControlTask(void *parameters)
|
|||||||
flightStatus.Armed = FLIGHTSTATUS_ARMED_DISARMED;
|
flightStatus.Armed = FLIGHTSTATUS_ARMED_DISARMED;
|
||||||
armState = ARM_STATE_DISARMED;
|
armState = ARM_STATE_DISARMED;
|
||||||
|
|
||||||
|
/* Initialize the RcvrActivty FSM */
|
||||||
|
portTickType lastActivityTime = xTaskGetTickCount();
|
||||||
|
resetRcvrActivity(&activity_fsm);
|
||||||
|
|
||||||
// Main task loop
|
// Main task loop
|
||||||
lastSysTime = xTaskGetTickCount();
|
lastSysTime = xTaskGetTickCount();
|
||||||
while (1) {
|
while (1) {
|
||||||
float scaledChannel[MANUALCONTROLCOMMAND_CHANNEL_NUMELEM];
|
float scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_NUMELEM];
|
||||||
|
|
||||||
// Wait until next update
|
// Wait until next update
|
||||||
vTaskDelayUntil(&lastSysTime, UPDATE_PERIOD_MS / portTICK_RATE_MS);
|
vTaskDelayUntil(&lastSysTime, UPDATE_PERIOD_MS / portTICK_RATE_MS);
|
||||||
@ -159,6 +177,18 @@ static void manualControlTask(void *parameters)
|
|||||||
// Read settings
|
// Read settings
|
||||||
ManualControlSettingsGet(&settings);
|
ManualControlSettingsGet(&settings);
|
||||||
|
|
||||||
|
/* Update channel activity monitor */
|
||||||
|
if (flightStatus.Armed == ARM_STATE_DISARMED) {
|
||||||
|
if (updateRcvrActivity(&activity_fsm)) {
|
||||||
|
/* Reset the aging timer because activity was detected */
|
||||||
|
lastActivityTime = lastSysTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timeDifferenceMs(lastActivityTime, lastSysTime) > 5000) {
|
||||||
|
resetRcvrActivity(&activity_fsm);
|
||||||
|
lastActivityTime = lastSysTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (ManualControlCommandReadOnly(&cmd)) {
|
if (ManualControlCommandReadOnly(&cmd)) {
|
||||||
FlightTelemetryStatsData flightTelemStats;
|
FlightTelemetryStatsData flightTelemStats;
|
||||||
FlightTelemetryStatsGet(&flightTelemStats);
|
FlightTelemetryStatsGet(&flightTelemStats);
|
||||||
@ -173,34 +203,64 @@ static void manualControlTask(void *parameters)
|
|||||||
|
|
||||||
if (!ManualControlCommandReadOnly(&cmd)) {
|
if (!ManualControlCommandReadOnly(&cmd)) {
|
||||||
|
|
||||||
|
bool valid_input_detected = true;
|
||||||
|
|
||||||
// Read channel values in us
|
// Read channel values in us
|
||||||
for (int n = 0; n < MANUALCONTROLCOMMAND_CHANNEL_NUMELEM; ++n) {
|
for (uint8_t n = 0;
|
||||||
if (pios_rcvr_channel_to_id_map[n].id) {
|
n < MANUALCONTROLSETTINGS_CHANNELGROUPS_NUMELEM && n < MANUALCONTROLCOMMAND_CHANNEL_NUMELEM;
|
||||||
cmd.Channel[n] = PIOS_RCVR_Read(pios_rcvr_channel_to_id_map[n].id,
|
++n) {
|
||||||
pios_rcvr_channel_to_id_map[n].channel);
|
extern uint32_t pios_rcvr_group_map[];
|
||||||
|
|
||||||
|
if (settings.ChannelGroups[n] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
cmd.Channel[n] = PIOS_RCVR_INVALID;
|
||||||
} else {
|
} else {
|
||||||
cmd.Channel[n] = -1;
|
cmd.Channel[n] = PIOS_RCVR_Read(pios_rcvr_group_map[settings.ChannelGroups[n]],
|
||||||
|
settings.ChannelNumber[n]);
|
||||||
}
|
}
|
||||||
scaledChannel[n] = scaleChannel(cmd.Channel[n], settings.ChannelMax[n], settings.ChannelMin[n], settings.ChannelNeutral[n]);
|
|
||||||
|
// If a channel has timed out this is not valid data and we shouldn't update anything
|
||||||
|
// until we decide to go to failsafe
|
||||||
|
if(cmd.Channel[n] == PIOS_RCVR_TIMEOUT)
|
||||||
|
valid_input_detected = false;
|
||||||
|
else
|
||||||
|
scaledChannel[n] = scaleChannel(cmd.Channel[n], settings.ChannelMax[n], settings.ChannelMin[n], settings.ChannelNeutral[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check settings, if error raise alarm
|
// Check settings, if error raise alarm
|
||||||
if (settings.Roll >= MANUALCONTROLSETTINGS_ROLL_NONE ||
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE ||
|
||||||
settings.Pitch >= MANUALCONTROLSETTINGS_PITCH_NONE ||
|
settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE ||
|
||||||
settings.Yaw >= MANUALCONTROLSETTINGS_YAW_NONE ||
|
settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE ||
|
||||||
settings.Throttle >= MANUALCONTROLSETTINGS_THROTTLE_NONE ||
|
settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE ||
|
||||||
settings.FlightMode >= MANUALCONTROLSETTINGS_FLIGHTMODE_NONE) {
|
settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_FLIGHTMODE] >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE ||
|
||||||
|
// Check all channel mappings are valid
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL] == (uint16_t) PIOS_RCVR_INVALID ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH] == (uint16_t) PIOS_RCVR_INVALID ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW] == (uint16_t) PIOS_RCVR_INVALID ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE] == (uint16_t) PIOS_RCVR_INVALID ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_FLIGHTMODE] == (uint16_t) PIOS_RCVR_INVALID ||
|
||||||
|
// Check the driver is exists
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL] == (uint16_t) PIOS_RCVR_NODRIVER ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH] == (uint16_t) PIOS_RCVR_NODRIVER ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW] == (uint16_t) PIOS_RCVR_NODRIVER ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE] == (uint16_t) PIOS_RCVR_NODRIVER ||
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_FLIGHTMODE] == (uint16_t) PIOS_RCVR_NODRIVER) {
|
||||||
|
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_CRITICAL);
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_CRITICAL);
|
||||||
cmd.Connected = MANUALCONTROLCOMMAND_CONNECTED_FALSE;
|
cmd.Connected = MANUALCONTROLCOMMAND_CONNECTED_FALSE;
|
||||||
ManualControlCommandSet(&cmd);
|
ManualControlCommandSet(&cmd);
|
||||||
|
|
||||||
|
// Need to do this here since we don't process armed status. Since this shouldn't happen in flight (changed config)
|
||||||
|
// immediately disarm
|
||||||
|
setArmedIfChanged(FLIGHTSTATUS_ARMED_DISARMED);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// decide if we have valid manual input or not
|
// decide if we have valid manual input or not
|
||||||
bool valid_input_detected = validInputRange(settings.ChannelMin[settings.Throttle], settings.ChannelMax[settings.Throttle], cmd.Channel[settings.Throttle]) &&
|
valid_input_detected &= validInputRange(settings.ChannelMin[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE], settings.ChannelMax[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE], cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE]) &&
|
||||||
validInputRange(settings.ChannelMin[settings.Roll], settings.ChannelMax[settings.Roll], cmd.Channel[settings.Roll]) &&
|
validInputRange(settings.ChannelMin[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL], settings.ChannelMax[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL], cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL]) &&
|
||||||
validInputRange(settings.ChannelMin[settings.Yaw], settings.ChannelMax[settings.Yaw], cmd.Channel[settings.Yaw]) &&
|
validInputRange(settings.ChannelMin[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW], settings.ChannelMax[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW], cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW]) &&
|
||||||
validInputRange(settings.ChannelMin[settings.Pitch], settings.ChannelMax[settings.Pitch], cmd.Channel[settings.Pitch]);
|
validInputRange(settings.ChannelMin[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH], settings.ChannelMax[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH], cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH]);
|
||||||
|
|
||||||
// Implement hysteresis loop on connection status
|
// Implement hysteresis loop on connection status
|
||||||
if (valid_input_detected && (++connected_count > 10)) {
|
if (valid_input_detected && (++connected_count > 10)) {
|
||||||
@ -218,55 +278,88 @@ static void manualControlTask(void *parameters)
|
|||||||
cmd.Roll = 0;
|
cmd.Roll = 0;
|
||||||
cmd.Yaw = 0;
|
cmd.Yaw = 0;
|
||||||
cmd.Pitch = 0;
|
cmd.Pitch = 0;
|
||||||
|
cmd.Collective = 0;
|
||||||
//cmd.FlightMode = MANUALCONTROLCOMMAND_FLIGHTMODE_AUTO; // don't do until AUTO implemented and functioning
|
//cmd.FlightMode = MANUALCONTROLCOMMAND_FLIGHTMODE_AUTO; // don't do until AUTO implemented and functioning
|
||||||
// Important: Throttle < 0 will reset Stabilization coefficients among other things. Either change this,
|
// Important: Throttle < 0 will reset Stabilization coefficients among other things. Either change this,
|
||||||
// or leave throttle at IDLE speed or above when going into AUTO-failsafe.
|
// or leave throttle at IDLE speed or above when going into AUTO-failsafe.
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
ManualControlCommandSet(&cmd);
|
|
||||||
} else {
|
|
||||||
AlarmsClear(SYSTEMALARMS_ALARM_MANUALCONTROL);
|
|
||||||
|
|
||||||
// Scale channels to -1 -> +1 range
|
|
||||||
cmd.Roll = scaledChannel[settings.Roll];
|
|
||||||
cmd.Pitch = scaledChannel[settings.Pitch];
|
|
||||||
cmd.Yaw = scaledChannel[settings.Yaw];
|
|
||||||
cmd.Throttle = scaledChannel[settings.Throttle];
|
|
||||||
flightMode = scaledChannel[settings.FlightMode];
|
|
||||||
|
|
||||||
AccessoryDesiredData accessory;
|
AccessoryDesiredData accessory;
|
||||||
// Set Accessory 0
|
// Set Accessory 0
|
||||||
if(settings.Accessory0 != MANUALCONTROLSETTINGS_ACCESSORY0_NONE) {
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY0] !=
|
||||||
accessory.AccessoryVal = scaledChannel[settings.Accessory0];
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = 0;
|
||||||
if(AccessoryDesiredInstSet(0, &accessory) != 0)
|
if(AccessoryDesiredInstSet(0, &accessory) != 0)
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
}
|
}
|
||||||
// Set Accessory 1
|
// Set Accessory 1
|
||||||
if(settings.Accessory1 != MANUALCONTROLSETTINGS_ACCESSORY1_NONE) {
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY1] !=
|
||||||
accessory.AccessoryVal = scaledChannel[settings.Accessory1];
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = 0;
|
||||||
if(AccessoryDesiredInstSet(1, &accessory) != 0)
|
if(AccessoryDesiredInstSet(1, &accessory) != 0)
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
}
|
}
|
||||||
// Set Accsesory 2
|
// Set Accessory 2
|
||||||
if(settings.Accessory2 != MANUALCONTROLSETTINGS_ACCESSORY2_NONE) {
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY2] !=
|
||||||
accessory.AccessoryVal = scaledChannel[settings.Accessory2];
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = 0;
|
||||||
|
if(AccessoryDesiredInstSet(2, &accessory) != 0)
|
||||||
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
AlarmsClear(SYSTEMALARMS_ALARM_MANUALCONTROL);
|
||||||
|
|
||||||
|
// Scale channels to -1 -> +1 range
|
||||||
|
cmd.Roll = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ROLL];
|
||||||
|
cmd.Pitch = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_PITCH];
|
||||||
|
cmd.Yaw = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_YAW];
|
||||||
|
cmd.Throttle = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_THROTTLE];
|
||||||
|
flightMode = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_FLIGHTMODE];
|
||||||
|
|
||||||
|
if(cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_INVALID &&
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_NODRIVER &&
|
||||||
|
cmd.Channel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE] != PIOS_RCVR_TIMEOUT)
|
||||||
|
cmd.Collective = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_COLLECTIVE];
|
||||||
|
|
||||||
|
AccessoryDesiredData accessory;
|
||||||
|
// Set Accessory 0
|
||||||
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY0] !=
|
||||||
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY0];
|
||||||
|
if(AccessoryDesiredInstSet(0, &accessory) != 0)
|
||||||
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
|
}
|
||||||
|
// Set Accessory 1
|
||||||
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY1] !=
|
||||||
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY1];
|
||||||
|
if(AccessoryDesiredInstSet(1, &accessory) != 0)
|
||||||
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
|
}
|
||||||
|
// Set Accessory 2
|
||||||
|
if (settings.ChannelGroups[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY2] !=
|
||||||
|
MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
accessory.AccessoryVal = scaledChannel[MANUALCONTROLSETTINGS_CHANNELGROUPS_ACCESSORY2];
|
||||||
if(AccessoryDesiredInstSet(2, &accessory) != 0)
|
if(AccessoryDesiredInstSet(2, &accessory) != 0)
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
AlarmsSet(SYSTEMALARMS_ALARM_MANUALCONTROL, SYSTEMALARMS_ALARM_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
processFlightMode(&settings, flightMode);
|
processFlightMode(&settings, flightMode);
|
||||||
processArm(&cmd, &settings);
|
|
||||||
|
|
||||||
// Update cmd object
|
|
||||||
ManualControlCommandSet(&cmd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process arming outside conditional so system will disarm when disconnected
|
||||||
|
processArm(&cmd, &settings);
|
||||||
|
|
||||||
|
// Update cmd object
|
||||||
|
ManualControlCommandSet(&cmd);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ManualControlCommandGet(&cmd); /* Under GCS control */
|
ManualControlCommandGet(&cmd); /* Under GCS control */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FlightStatusGet(&flightStatus);
|
FlightStatusGet(&flightStatus);
|
||||||
|
|
||||||
// Depending on the mode update the Stabilization or Actuator objects
|
// Depending on the mode update the Stabilization or Actuator objects
|
||||||
@ -288,6 +381,145 @@ static void manualControlTask(void *parameters)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resetRcvrActivity(struct rcvr_activity_fsm * fsm)
|
||||||
|
{
|
||||||
|
ReceiverActivityData data;
|
||||||
|
bool updated = false;
|
||||||
|
|
||||||
|
/* Clear all channel activity flags */
|
||||||
|
ReceiverActivityGet(&data);
|
||||||
|
if (data.ActiveGroup != RECEIVERACTIVITY_ACTIVEGROUP_NONE &&
|
||||||
|
data.ActiveChannel != 255) {
|
||||||
|
data.ActiveGroup = RECEIVERACTIVITY_ACTIVEGROUP_NONE;
|
||||||
|
data.ActiveChannel = 255;
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
ReceiverActivitySet(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the FSM state */
|
||||||
|
fsm->group = 0;
|
||||||
|
fsm->sample_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateRcvrActivitySample(uint32_t rcvr_id, uint16_t samples[], uint8_t max_channels) {
|
||||||
|
for (uint8_t channel = 1; channel <= max_channels; channel++) {
|
||||||
|
// Subtract 1 because channels are 1 indexed
|
||||||
|
samples[channel - 1] = PIOS_RCVR_Read(rcvr_id, channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool updateRcvrActivityCompare(uint32_t rcvr_id, struct rcvr_activity_fsm * fsm)
|
||||||
|
{
|
||||||
|
bool activity_updated = false;
|
||||||
|
|
||||||
|
/* Compare the current value to the previous sampled value */
|
||||||
|
for (uint8_t channel = 1;
|
||||||
|
channel <= RCVR_ACTIVITY_MONITOR_CHANNELS_PER_GROUP;
|
||||||
|
channel++) {
|
||||||
|
uint16_t delta;
|
||||||
|
uint16_t prev = fsm->prev[channel - 1]; // Subtract 1 because channels are 1 indexed
|
||||||
|
uint16_t curr = PIOS_RCVR_Read(rcvr_id, channel);
|
||||||
|
if (curr > prev) {
|
||||||
|
delta = curr - prev;
|
||||||
|
} else {
|
||||||
|
delta = prev - curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > RCVR_ACTIVITY_MONITOR_MIN_RANGE) {
|
||||||
|
/* Mark this channel as active */
|
||||||
|
ReceiverActivityActiveGroupOptions group;
|
||||||
|
|
||||||
|
/* Don't assume manualcontrolsettings and receiveractivity are in the same order. */
|
||||||
|
switch (fsm->group) {
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_PWM:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_PWM;
|
||||||
|
break;
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_PPM:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_PPM;
|
||||||
|
break;
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_SPEKTRUM1;
|
||||||
|
break;
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM2:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_SPEKTRUM2;
|
||||||
|
break;
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SBUS:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_SBUS;
|
||||||
|
break;
|
||||||
|
case MANUALCONTROLSETTINGS_CHANNELGROUPS_GCS:
|
||||||
|
group = RECEIVERACTIVITY_ACTIVEGROUP_GCS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PIOS_Assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReceiverActivityActiveGroupSet(&group);
|
||||||
|
ReceiverActivityActiveChannelSet(&channel);
|
||||||
|
activity_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (activity_updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool updateRcvrActivity(struct rcvr_activity_fsm * fsm)
|
||||||
|
{
|
||||||
|
bool activity_updated = false;
|
||||||
|
|
||||||
|
if (fsm->group >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
/* We're out of range, reset things */
|
||||||
|
resetRcvrActivity(fsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint32_t pios_rcvr_group_map[];
|
||||||
|
if (!pios_rcvr_group_map[fsm->group]) {
|
||||||
|
/* Unbound group, skip it */
|
||||||
|
goto group_completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fsm->sample_count == 0) {
|
||||||
|
/* Take a sample of each channel in this group */
|
||||||
|
updateRcvrActivitySample(pios_rcvr_group_map[fsm->group],
|
||||||
|
fsm->prev,
|
||||||
|
NELEMENTS(fsm->prev));
|
||||||
|
fsm->sample_count++;
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare with previous sample */
|
||||||
|
activity_updated = updateRcvrActivityCompare(pios_rcvr_group_map[fsm->group], fsm);
|
||||||
|
|
||||||
|
group_completed:
|
||||||
|
/* Reset the sample counter */
|
||||||
|
fsm->sample_count = 0;
|
||||||
|
|
||||||
|
/* Find the next active group, but limit search so we can't loop forever here */
|
||||||
|
for (uint8_t i = 0; i < MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE; i++) {
|
||||||
|
/* Move to the next group */
|
||||||
|
fsm->group++;
|
||||||
|
if (fsm->group >= MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE) {
|
||||||
|
/* Wrap back to the first group */
|
||||||
|
fsm->group = 0;
|
||||||
|
}
|
||||||
|
if (pios_rcvr_group_map[fsm->group]) {
|
||||||
|
/*
|
||||||
|
* Found an active group, take a sample here to avoid an
|
||||||
|
* extra 20ms delay in the main thread so we can speed up
|
||||||
|
* this algorithm.
|
||||||
|
*/
|
||||||
|
updateRcvrActivitySample(pios_rcvr_group_map[fsm->group],
|
||||||
|
fsm->prev,
|
||||||
|
NELEMENTS(fsm->prev));
|
||||||
|
fsm->sample_count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (activity_updated);
|
||||||
|
}
|
||||||
|
|
||||||
static void updateActuatorDesired(ManualControlCommandData * cmd)
|
static void updateActuatorDesired(ManualControlCommandData * cmd)
|
||||||
{
|
{
|
||||||
ActuatorDesiredData actuator;
|
ActuatorDesiredData actuator;
|
||||||
@ -449,7 +681,7 @@ static void processArm(ManualControlCommandData * cmd, ManualControlSettingsData
|
|||||||
} else {
|
} else {
|
||||||
// Not really needed since this function not called when disconnected
|
// Not really needed since this function not called when disconnected
|
||||||
if (cmd->Connected == MANUALCONTROLCOMMAND_CONNECTED_FALSE)
|
if (cmd->Connected == MANUALCONTROLCOMMAND_CONNECTED_FALSE)
|
||||||
return;
|
lowThrottle = true;
|
||||||
|
|
||||||
// The throttle is not low, in case we where arming or disarming, abort
|
// The throttle is not low, in case we where arming or disarming, abort
|
||||||
if (!lowThrottle) {
|
if (!lowThrottle) {
|
||||||
|
@ -235,6 +235,9 @@ static void stabilizationTask(void* parameters)
|
|||||||
{
|
{
|
||||||
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
|
||||||
rateDesiredAxis[i] = attitudeDesiredAxis[i];
|
rateDesiredAxis[i] = attitudeDesiredAxis[i];
|
||||||
|
|
||||||
|
// Zero attitude and axis lock accumulators
|
||||||
|
pids[PID_ROLL + i].iAccumulator = 0;
|
||||||
axis_lock_accum[i] = 0;
|
axis_lock_accum[i] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -249,11 +252,20 @@ static void stabilizationTask(void* parameters)
|
|||||||
|
|
||||||
rateDesiredAxis[i] = attitudeDesiredAxis[i] + weak_leveling;
|
rateDesiredAxis[i] = attitudeDesiredAxis[i] + weak_leveling;
|
||||||
|
|
||||||
|
// Zero attitude and axis lock accumulators
|
||||||
|
pids[PID_ROLL + i].iAccumulator = 0;
|
||||||
axis_lock_accum[i] = 0;
|
axis_lock_accum[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
|
||||||
rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], local_error[i]);
|
rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], local_error[i]);
|
||||||
|
|
||||||
|
if(rateDesiredAxis[i] > settings.MaximumRate[i])
|
||||||
|
rateDesiredAxis[i] = settings.MaximumRate[i];
|
||||||
|
else if(rateDesiredAxis[i] < -settings.MaximumRate[i])
|
||||||
|
rateDesiredAxis[i] = -settings.MaximumRate[i];
|
||||||
|
|
||||||
|
|
||||||
axis_lock_accum[i] = 0;
|
axis_lock_accum[i] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -272,6 +284,12 @@ static void stabilizationTask(void* parameters)
|
|||||||
|
|
||||||
rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], axis_lock_accum[i]);
|
rateDesiredAxis[i] = ApplyPid(&pids[PID_ROLL + i], axis_lock_accum[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(rateDesiredAxis[i] > settings.MaximumRate[i])
|
||||||
|
rateDesiredAxis[i] = settings.MaximumRate[i];
|
||||||
|
else if(rateDesiredAxis[i] < -settings.MaximumRate[i])
|
||||||
|
rateDesiredAxis[i] = -settings.MaximumRate[i];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,11 +302,6 @@ static void stabilizationTask(void* parameters)
|
|||||||
//Calculate desired command
|
//Calculate desired command
|
||||||
for(int8_t ct=0; ct< MAX_AXES; ct++)
|
for(int8_t ct=0; ct< MAX_AXES; ct++)
|
||||||
{
|
{
|
||||||
if(rateDesiredAxis[ct] > settings.MaximumRate[ct])
|
|
||||||
rateDesiredAxis[ct] = settings.MaximumRate[ct];
|
|
||||||
else if(rateDesiredAxis[ct] < -settings.MaximumRate[ct])
|
|
||||||
rateDesiredAxis[ct] = -settings.MaximumRate[ct];
|
|
||||||
|
|
||||||
switch(stabDesired.StabilizationMode[ct])
|
switch(stabDesired.StabilizationMode[ct])
|
||||||
{
|
{
|
||||||
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
|
||||||
@ -306,14 +319,20 @@ static void stabilizationTask(void* parameters)
|
|||||||
case ROLL:
|
case ROLL:
|
||||||
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
||||||
shouldUpdate = 1;
|
shouldUpdate = 1;
|
||||||
|
pids[PID_RATE_ROLL].iAccumulator = 0;
|
||||||
|
pids[PID_ROLL].iAccumulator = 0;
|
||||||
break;
|
break;
|
||||||
case PITCH:
|
case PITCH:
|
||||||
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
||||||
shouldUpdate = 1;
|
shouldUpdate = 1;
|
||||||
|
pids[PID_RATE_PITCH].iAccumulator = 0;
|
||||||
|
pids[PID_PITCH].iAccumulator = 0;
|
||||||
break;
|
break;
|
||||||
case YAW:
|
case YAW:
|
||||||
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
actuatorDesiredAxis[ct] = bound(attitudeDesiredAxis[ct]);
|
||||||
shouldUpdate = 1;
|
shouldUpdate = 1;
|
||||||
|
pids[PID_RATE_YAW].iAccumulator = 0;
|
||||||
|
pids[PID_YAW].iAccumulator = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -76,7 +76,8 @@
|
|||||||
static uint32_t idleCounter;
|
static uint32_t idleCounter;
|
||||||
static uint32_t idleCounterClear;
|
static uint32_t idleCounterClear;
|
||||||
static xTaskHandle systemTaskHandle;
|
static xTaskHandle systemTaskHandle;
|
||||||
static int32_t stackOverflow;
|
static bool stackOverflow;
|
||||||
|
static bool mallocFailed;
|
||||||
|
|
||||||
// Private functions
|
// Private functions
|
||||||
static void objectUpdatedCb(UAVObjEvent * ev);
|
static void objectUpdatedCb(UAVObjEvent * ev);
|
||||||
@ -94,7 +95,8 @@ static void updateWDGstats();
|
|||||||
int32_t SystemModStart(void)
|
int32_t SystemModStart(void)
|
||||||
{
|
{
|
||||||
// Initialize vars
|
// Initialize vars
|
||||||
stackOverflow = 0;
|
stackOverflow = false;
|
||||||
|
mallocFailed = false;
|
||||||
// Create system task
|
// Create system task
|
||||||
xTaskCreate(systemTask, (signed char *)"System", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &systemTaskHandle);
|
xTaskCreate(systemTask, (signed char *)"System", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &systemTaskHandle);
|
||||||
// Register task
|
// Register task
|
||||||
@ -423,12 +425,19 @@ static void updateSystemAlarms()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for stack overflow
|
// Check for stack overflow
|
||||||
if (stackOverflow == 1) {
|
if (stackOverflow) {
|
||||||
AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW, SYSTEMALARMS_ALARM_CRITICAL);
|
AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW, SYSTEMALARMS_ALARM_CRITICAL);
|
||||||
} else {
|
} else {
|
||||||
AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW);
|
AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for malloc failures
|
||||||
|
if (mallocFailed) {
|
||||||
|
AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY, SYSTEMALARMS_ALARM_CRITICAL);
|
||||||
|
} else {
|
||||||
|
AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_SDCARD)
|
#if defined(PIOS_INCLUDE_SDCARD)
|
||||||
// Check for SD card
|
// Check for SD card
|
||||||
if (PIOS_SDCARD_IsMounted() == 0) {
|
if (PIOS_SDCARD_IsMounted() == 0) {
|
||||||
@ -467,9 +476,29 @@ void vApplicationIdleHook(void)
|
|||||||
/**
|
/**
|
||||||
* Called by the RTOS when a stack overflow is detected.
|
* Called by the RTOS when a stack overflow is detected.
|
||||||
*/
|
*/
|
||||||
|
#define DEBUG_STACK_OVERFLOW 0
|
||||||
void vApplicationStackOverflowHook(xTaskHandle * pxTask, signed portCHAR * pcTaskName)
|
void vApplicationStackOverflowHook(xTaskHandle * pxTask, signed portCHAR * pcTaskName)
|
||||||
{
|
{
|
||||||
stackOverflow = 1;
|
stackOverflow = true;
|
||||||
|
#if DEBUG_STACK_OVERFLOW
|
||||||
|
static volatile bool wait_here = true;
|
||||||
|
while(wait_here);
|
||||||
|
wait_here = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the RTOS when a malloc call fails.
|
||||||
|
*/
|
||||||
|
#define DEBUG_MALLOC_FAILURES 0
|
||||||
|
void vApplicationMallocFailedHook(void)
|
||||||
|
{
|
||||||
|
mallocFailed = true;
|
||||||
|
#if DEBUG_MALLOC_FAILURES
|
||||||
|
static volatile bool wait_here = true;
|
||||||
|
while(wait_here);
|
||||||
|
wait_here = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,6 +171,7 @@ SRC += $(PIOSSTM32F10X)/pios_ppm.c
|
|||||||
SRC += $(PIOSSTM32F10X)/pios_pwm.c
|
SRC += $(PIOSSTM32F10X)/pios_pwm.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_spektrum.c
|
SRC += $(PIOSSTM32F10X)/pios_spektrum.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_sbus.c
|
SRC += $(PIOSSTM32F10X)/pios_sbus.c
|
||||||
|
SRC += $(PIOSSTM32F10X)/pios_tim.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_debug.c
|
SRC += $(PIOSSTM32F10X)/pios_debug.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_gpio.c
|
SRC += $(PIOSSTM32F10X)/pios_gpio.c
|
||||||
SRC += $(PIOSSTM32F10X)/pios_exti.c
|
SRC += $(PIOSSTM32F10X)/pios_exti.c
|
||||||
@ -535,7 +536,7 @@ $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin
|
|||||||
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
||||||
|
|
||||||
# Add jtag targets (program and wipe)
|
# Add jtag targets (program and wipe)
|
||||||
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE)))
|
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG)))
|
||||||
|
|
||||||
.PHONY: elf lss sym hex bin bino opfw
|
.PHONY: elf lss sym hex bin bino opfw
|
||||||
elf: $(OUTDIR)/$(TARGET).elf
|
elf: $(OUTDIR)/$(TARGET).elf
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define configUSE_PREEMPTION 1
|
#define configUSE_PREEMPTION 1
|
||||||
#define configUSE_IDLE_HOOK 1
|
#define configUSE_IDLE_HOOK 1
|
||||||
#define configUSE_TICK_HOOK 0
|
#define configUSE_TICK_HOOK 0
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
|
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
|
||||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
#define PIOS_INCLUDE_SPEKTRUM
|
#define PIOS_INCLUDE_SPEKTRUM
|
||||||
//#define PIOS_INCLUDE_SBUS
|
//#define PIOS_INCLUDE_SBUS
|
||||||
#define PIOS_INCLUDE_PWM
|
#define PIOS_INCLUDE_PWM
|
||||||
//#define PIOS_INCLUDE_PPM
|
#define PIOS_INCLUDE_PPM
|
||||||
|
|
||||||
#define PIOS_INCLUDE_TELEMETRY_RF
|
#define PIOS_INCLUDE_TELEMETRY_RF
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include <pios.h>
|
#include <pios.h>
|
||||||
#include <openpilot.h>
|
#include <openpilot.h>
|
||||||
#include <uavobjectsinit.h>
|
#include <uavobjectsinit.h>
|
||||||
#include "manualcontrolsettings.h"
|
#include <hwsettings.h>
|
||||||
#include "hwsettings.h"
|
#include <manualcontrolsettings.h>
|
||||||
|
|
||||||
//#define I2C_DEBUG_PIN 0
|
//#define I2C_DEBUG_PIN 0
|
||||||
//#define USART_GPS_DEBUG_PIN 1
|
//#define USART_GPS_DEBUG_PIN 1
|
||||||
@ -302,6 +302,89 @@ void PIOS_ADC_handler() {
|
|||||||
PIOS_ADC_DMA_Handler();
|
PIOS_ADC_DMA_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "pios_tim_priv.h"
|
||||||
|
|
||||||
|
static const TIM_TimeBaseInitTypeDef tim_4_8_time_base = {
|
||||||
|
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
||||||
|
.TIM_ClockDivision = TIM_CKD_DIV1,
|
||||||
|
.TIM_CounterMode = TIM_CounterMode_Up,
|
||||||
|
.TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1),
|
||||||
|
.TIM_RepetitionCounter = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_4_cfg = {
|
||||||
|
.timer = TIM4,
|
||||||
|
.time_base_init = &tim_4_8_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM4_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_8_cfg = {
|
||||||
|
.timer = TIM8,
|
||||||
|
.time_base_init = &tim_4_8_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM8_CC_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TIM_TimeBaseInitTypeDef tim_1_3_5_time_base = {
|
||||||
|
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
||||||
|
.TIM_ClockDivision = TIM_CKD_DIV1,
|
||||||
|
.TIM_CounterMode = TIM_CounterMode_Up,
|
||||||
|
.TIM_Period = 0xFFFF,
|
||||||
|
.TIM_RepetitionCounter = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_1_cfg = {
|
||||||
|
.timer = TIM1,
|
||||||
|
.time_base_init = &tim_1_3_5_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM1_CC_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_3_cfg = {
|
||||||
|
.timer = TIM3,
|
||||||
|
.time_base_init = &tim_1_3_5_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM3_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pios_tim_clock_cfg tim_5_cfg = {
|
||||||
|
.timer = TIM5,
|
||||||
|
.time_base_init = &tim_1_3_5_time_base,
|
||||||
|
.irq = {
|
||||||
|
.init = {
|
||||||
|
.NVIC_IRQChannel = TIM5_IRQn,
|
||||||
|
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||||
|
.NVIC_IRQChannelSubPriority = 0,
|
||||||
|
.NVIC_IRQChannelCmd = ENABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_USART)
|
#if defined(PIOS_INCLUDE_USART)
|
||||||
|
|
||||||
#include "pios_usart_priv.h"
|
#include "pios_usart_priv.h"
|
||||||
@ -497,7 +580,6 @@ static const struct pios_usart_cfg pios_usart_spektrum_cfg = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <pios_spektrum_priv.h>
|
|
||||||
static const struct pios_spektrum_cfg pios_spektrum_cfg = {
|
static const struct pios_spektrum_cfg pios_spektrum_cfg = {
|
||||||
.bind = {
|
.bind = {
|
||||||
.gpio = GPIOA,
|
.gpio = GPIOA,
|
||||||
@ -536,65 +618,106 @@ static const struct pios_spektrum_cfg pios_spektrum_cfg = {
|
|||||||
* Pios servo configuration structures
|
* Pios servo configuration structures
|
||||||
*/
|
*/
|
||||||
#include <pios_servo_priv.h>
|
#include <pios_servo_priv.h>
|
||||||
static const struct pios_servo_channel pios_servo_channels[] = {
|
static const struct pios_tim_channel pios_tim_servoport_all_pins[] = {
|
||||||
{
|
{
|
||||||
.timer = TIM4,
|
.timer = TIM4,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_1,
|
||||||
.channel = TIM_Channel_1,
|
.pin = {
|
||||||
.pin = GPIO_Pin_6,
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_6,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM4,
|
.timer = TIM4,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_2,
|
||||||
.channel = TIM_Channel_2,
|
.pin = {
|
||||||
.pin = GPIO_Pin_7,
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_7,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM4,
|
.timer = TIM4,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_3,
|
||||||
.channel = TIM_Channel_3,
|
.pin = {
|
||||||
.pin = GPIO_Pin_8,
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_8,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM4,
|
.timer = TIM4,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_4,
|
||||||
.channel = TIM_Channel_4,
|
.pin = {
|
||||||
.pin = GPIO_Pin_9,
|
.gpio = GPIOB,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_9,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM8,
|
.timer = TIM8,
|
||||||
.port = GPIOC,
|
.timer_chan = TIM_Channel_1,
|
||||||
.channel = TIM_Channel_1,
|
.pin = {
|
||||||
.pin = GPIO_Pin_6,
|
.gpio = GPIOC,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_6,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM8,
|
.timer = TIM8,
|
||||||
.port = GPIOC,
|
.timer_chan = TIM_Channel_2,
|
||||||
.channel = TIM_Channel_2,
|
.pin = {
|
||||||
.pin = GPIO_Pin_7,
|
.gpio = GPIOC,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_7,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM8,
|
.timer = TIM8,
|
||||||
.port = GPIOC,
|
.timer_chan = TIM_Channel_3,
|
||||||
.channel = TIM_Channel_3,
|
.pin = {
|
||||||
.pin = GPIO_Pin_8,
|
.gpio = GPIOC,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_8,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM8,
|
.timer = TIM8,
|
||||||
.port = GPIOC,
|
.timer_chan = TIM_Channel_4,
|
||||||
.channel = TIM_Channel_4,
|
.pin = {
|
||||||
.pin = GPIO_Pin_9,
|
.gpio = GPIOC,
|
||||||
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_9,
|
||||||
|
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct pios_servo_cfg pios_servo_cfg = {
|
const struct pios_servo_cfg pios_servo_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1),
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_oc_init = {
|
.tim_oc_init = {
|
||||||
.TIM_OCMode = TIM_OCMode_PWM1,
|
.TIM_OCMode = TIM_OCMode_PWM1,
|
||||||
.TIM_OutputState = TIM_OutputState_Enable,
|
.TIM_OutputState = TIM_OutputState_Enable,
|
||||||
@ -605,127 +728,127 @@ const struct pios_servo_cfg pios_servo_cfg = {
|
|||||||
.TIM_OCIdleState = TIM_OCIdleState_Reset,
|
.TIM_OCIdleState = TIM_OCIdleState_Reset,
|
||||||
.TIM_OCNIdleState = TIM_OCNIdleState_Reset,
|
.TIM_OCNIdleState = TIM_OCNIdleState_Reset,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
.channels = pios_tim_servoport_all_pins,
|
||||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
.num_channels = NELEMENTS(pios_tim_servoport_all_pins),
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
|
||||||
},
|
|
||||||
.remap = 0,
|
|
||||||
.channels = pios_servo_channels,
|
|
||||||
.num_channels = NELEMENTS(pios_servo_channels),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PWM Inputs
|
* PWM Inputs
|
||||||
*/
|
*/
|
||||||
#if defined(PIOS_INCLUDE_PWM)
|
#if defined(PIOS_INCLUDE_PWM) || defined(PIOS_INCLUDE_PPM)
|
||||||
#include <pios_pwm_priv.h>
|
#include <pios_pwm_priv.h>
|
||||||
static const struct pios_pwm_channel pios_pwm_channels[] = {
|
static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = {
|
||||||
{
|
{
|
||||||
.timer = TIM1,
|
.timer = TIM1,
|
||||||
.port = GPIOA,
|
.timer_chan = TIM_Channel_2,
|
||||||
.ccr = TIM_IT_CC2,
|
.pin = {
|
||||||
.channel = TIM_Channel_2,
|
.gpio = GPIOA,
|
||||||
.pin = GPIO_Pin_9,
|
.init = {
|
||||||
},
|
.GPIO_Pin = GPIO_Pin_9,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM1,
|
.timer = TIM1,
|
||||||
.port = GPIOA,
|
.timer_chan = TIM_Channel_3,
|
||||||
.ccr = TIM_IT_CC3,
|
.pin = {
|
||||||
.channel = TIM_Channel_3,
|
.gpio = GPIOA,
|
||||||
.pin = GPIO_Pin_10,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_10,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM5,
|
.timer = TIM5,
|
||||||
.port = GPIOA,
|
.timer_chan = TIM_Channel_1,
|
||||||
.ccr = TIM_IT_CC1,
|
.pin = {
|
||||||
.channel = TIM_Channel_1,
|
.gpio = GPIOA,
|
||||||
.pin = GPIO_Pin_0
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_0,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM1,
|
.timer = TIM1,
|
||||||
.port = GPIOA,
|
.timer_chan = TIM_Channel_1,
|
||||||
.ccr = TIM_IT_CC1,
|
.pin = {
|
||||||
.channel = TIM_Channel_1,
|
.gpio = GPIOA,
|
||||||
.pin = GPIO_Pin_8,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_8,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM3,
|
.timer = TIM3,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_4,
|
||||||
.ccr = TIM_IT_CC4,
|
.pin = {
|
||||||
.channel = TIM_Channel_4,
|
.gpio = GPIOB,
|
||||||
.pin = GPIO_Pin_1,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_1,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM3,
|
.timer = TIM3,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_3,
|
||||||
.ccr = TIM_IT_CC3,
|
.pin = {
|
||||||
.channel = TIM_Channel_3,
|
.gpio = GPIOB,
|
||||||
.pin = GPIO_Pin_0,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_0,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM3,
|
.timer = TIM3,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_1,
|
||||||
.ccr = TIM_IT_CC1,
|
.pin = {
|
||||||
.channel = TIM_Channel_1,
|
.gpio = GPIOB,
|
||||||
.pin = GPIO_Pin_4,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_4,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.remap = GPIO_PartialRemap_TIM3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.timer = TIM3,
|
.timer = TIM3,
|
||||||
.port = GPIOB,
|
.timer_chan = TIM_Channel_2,
|
||||||
.ccr = TIM_IT_CC2,
|
.pin = {
|
||||||
.channel = TIM_Channel_2,
|
.gpio = GPIOB,
|
||||||
.pin = GPIO_Pin_5,
|
.init = {
|
||||||
|
.GPIO_Pin = GPIO_Pin_5,
|
||||||
|
.GPIO_Mode = GPIO_Mode_IPD,
|
||||||
|
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.remap = GPIO_PartialRemap_TIM3,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void TIM1_CC_IRQHandler();
|
|
||||||
void TIM3_IRQHandler();
|
|
||||||
void TIM5_IRQHandler();
|
|
||||||
void TIM1_CC_IRQHandler() __attribute__ ((alias ("PIOS_TIM1_CC_irq_handler")));
|
|
||||||
void TIM3_IRQHandler() __attribute__ ((alias ("PIOS_TIM3_irq_handler")));
|
|
||||||
void TIM5_IRQHandler() __attribute__ ((alias ("PIOS_TIM5_irq_handler")));
|
|
||||||
const struct pios_pwm_cfg pios_pwm_cfg = {
|
const struct pios_pwm_cfg pios_pwm_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1,
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = 0xFFFF,
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_ic_init = {
|
.tim_ic_init = {
|
||||||
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
||||||
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
||||||
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
.TIM_ICPrescaler = TIM_ICPSC_DIV1,
|
||||||
.TIM_ICFilter = 0x0,
|
.TIM_ICFilter = 0x0,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
.channels = pios_tim_rcvrport_all_channels,
|
||||||
.GPIO_Mode = GPIO_Mode_IPD,
|
.num_channels = NELEMENTS(pios_tim_rcvrport_all_channels),
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
|
||||||
},
|
|
||||||
.remap = GPIO_PartialRemap_TIM3,
|
|
||||||
.irq = {
|
|
||||||
.init = {
|
|
||||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
|
||||||
.NVIC_IRQChannelSubPriority = 0,
|
|
||||||
.NVIC_IRQChannelCmd = ENABLE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.channels = pios_pwm_channels,
|
|
||||||
.num_channels = NELEMENTS(pios_pwm_channels),
|
|
||||||
};
|
};
|
||||||
void PIOS_TIM1_CC_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM1);
|
|
||||||
}
|
|
||||||
void PIOS_TIM3_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM3);
|
|
||||||
}
|
|
||||||
void PIOS_TIM5_irq_handler()
|
|
||||||
{
|
|
||||||
PIOS_PWM_irq_handler(TIM5);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -733,42 +856,7 @@ void PIOS_TIM5_irq_handler()
|
|||||||
*/
|
*/
|
||||||
#if defined(PIOS_INCLUDE_PPM)
|
#if defined(PIOS_INCLUDE_PPM)
|
||||||
#include <pios_ppm_priv.h>
|
#include <pios_ppm_priv.h>
|
||||||
void TIM6_IRQHandler();
|
|
||||||
void TIM6_IRQHandler() __attribute__ ((alias ("PIOS_TIM6_irq_handler")));
|
|
||||||
static const struct pios_ppmsv_cfg pios_ppmsv_cfg = {
|
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, /* For 1 uS accuracy */
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = ((1000000 / 25) - 1), /* 25 Hz */
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.irq = {
|
|
||||||
.init = {
|
|
||||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
|
||||||
.NVIC_IRQChannelSubPriority = 0,
|
|
||||||
.NVIC_IRQChannelCmd = ENABLE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.timer = TIM6,
|
|
||||||
.ccr = TIM_IT_Update,
|
|
||||||
};
|
|
||||||
|
|
||||||
void PIOS_TIM6_irq_handler(void)
|
|
||||||
{
|
|
||||||
PIOS_PPMSV_irq_handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TIM1_CC_IRQHandler();
|
|
||||||
void TIM1_CC_IRQHandler() __attribute__ ((alias ("PIOS_TIM1_CC_irq_handler")));
|
|
||||||
static const struct pios_ppm_cfg pios_ppm_cfg = {
|
static const struct pios_ppm_cfg pios_ppm_cfg = {
|
||||||
.tim_base_init = {
|
|
||||||
.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, /* For 1 uS accuracy */
|
|
||||||
.TIM_ClockDivision = TIM_CKD_DIV1,
|
|
||||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
|
||||||
.TIM_Period = 0xFFFF,
|
|
||||||
.TIM_RepetitionCounter = 0x0000,
|
|
||||||
},
|
|
||||||
.tim_ic_init = {
|
.tim_ic_init = {
|
||||||
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
.TIM_ICPolarity = TIM_ICPolarity_Rising,
|
||||||
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
.TIM_ICSelection = TIM_ICSelection_DirectTI,
|
||||||
@ -776,30 +864,11 @@ static const struct pios_ppm_cfg pios_ppm_cfg = {
|
|||||||
.TIM_ICFilter = 0x0,
|
.TIM_ICFilter = 0x0,
|
||||||
.TIM_Channel = TIM_Channel_2,
|
.TIM_Channel = TIM_Channel_2,
|
||||||
},
|
},
|
||||||
.gpio_init = {
|
/* Use only the first channel for ppm */
|
||||||
.GPIO_Mode = GPIO_Mode_IPD,
|
.channels = &pios_tim_rcvrport_all_channels[0],
|
||||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
.num_channels = 1,
|
||||||
.GPIO_Pin = GPIO_Pin_9,
|
|
||||||
},
|
|
||||||
.remap = 0,
|
|
||||||
.irq = {
|
|
||||||
.init = {
|
|
||||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
|
||||||
.NVIC_IRQChannelSubPriority = 0,
|
|
||||||
.NVIC_IRQChannelCmd = ENABLE,
|
|
||||||
.NVIC_IRQChannel = TIM1_CC_IRQn,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.timer = TIM1,
|
|
||||||
.port = GPIOA,
|
|
||||||
.ccr = TIM_IT_CC2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void PIOS_TIM1_CC_irq_handler(void)
|
|
||||||
{
|
|
||||||
PIOS_PPM_irq_handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //PPM
|
#endif //PPM
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_I2C)
|
#if defined(PIOS_INCLUDE_I2C)
|
||||||
@ -965,8 +1034,12 @@ static const struct stm32_gpio pios_debug_pins[] = {
|
|||||||
#if defined(PIOS_INCLUDE_RCVR)
|
#if defined(PIOS_INCLUDE_RCVR)
|
||||||
#include "pios_rcvr_priv.h"
|
#include "pios_rcvr_priv.h"
|
||||||
|
|
||||||
struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[PIOS_RCVR_MAX_CHANNELS];
|
/* One slot per selectable receiver group.
|
||||||
uint32_t pios_rcvr_max_channel;
|
* eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS
|
||||||
|
* NOTE: No slot in this map for NONE.
|
||||||
|
*/
|
||||||
|
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];
|
||||||
|
|
||||||
#endif /* PIOS_INCLUDE_RCVR */
|
#endif /* PIOS_INCLUDE_RCVR */
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_USB_HID)
|
#if defined(PIOS_INCLUDE_USB_HID)
|
||||||
@ -1004,8 +1077,9 @@ void PIOS_Board_Init(void) {
|
|||||||
/* Remap AFIO pin */
|
/* Remap AFIO pin */
|
||||||
//GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE);
|
//GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE);
|
||||||
|
|
||||||
/* Debug services */
|
#ifdef PIOS_DEBUG_ENABLE_DEBUG_PINS
|
||||||
PIOS_DEBUG_Init();
|
PIOS_DEBUG_Init(&pios_tim_servo_all_channels, NELEMENTS(pios_tim_servo_all_channels));
|
||||||
|
#endif /* PIOS_DEBUG_ENABLE_DEBUG_PINS */
|
||||||
|
|
||||||
/* Delay system */
|
/* Delay system */
|
||||||
PIOS_DELAY_Init();
|
PIOS_DELAY_Init();
|
||||||
@ -1026,7 +1100,6 @@ void PIOS_Board_Init(void) {
|
|||||||
UAVObjInitialize();
|
UAVObjInitialize();
|
||||||
|
|
||||||
HwSettingsInitialize();
|
HwSettingsInitialize();
|
||||||
ManualControlSettingsInitialize();
|
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_RTC)
|
#if defined(PIOS_INCLUDE_RTC)
|
||||||
/* Initialize the real-time clock and its associated tick */
|
/* Initialize the real-time clock and its associated tick */
|
||||||
@ -1039,6 +1112,14 @@ void PIOS_Board_Init(void) {
|
|||||||
/* Initialize the task monitor library */
|
/* Initialize the task monitor library */
|
||||||
TaskMonitorInitialize();
|
TaskMonitorInitialize();
|
||||||
|
|
||||||
|
/* Set up pulse timers */
|
||||||
|
PIOS_TIM_InitClock(&tim_1_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_3_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_5_cfg);
|
||||||
|
|
||||||
|
PIOS_TIM_InitClock(&tim_4_cfg);
|
||||||
|
PIOS_TIM_InitClock(&tim_8_cfg);
|
||||||
|
|
||||||
/* Prepare the AHRS Comms upper layer protocol */
|
/* Prepare the AHRS Comms upper layer protocol */
|
||||||
AhrsInitComms();
|
AhrsInitComms();
|
||||||
|
|
||||||
@ -1050,127 +1131,128 @@ void PIOS_Board_Init(void) {
|
|||||||
/* Bind the AHRS comms layer to the AHRS SPI link */
|
/* Bind the AHRS comms layer to the AHRS SPI link */
|
||||||
AhrsConnect(pios_spi_ahrs_id);
|
AhrsConnect(pios_spi_ahrs_id);
|
||||||
|
|
||||||
/* Initialize the PiOS library */
|
/* Configure the main IO port */
|
||||||
#if defined(PIOS_INCLUDE_COM)
|
uint8_t hwsettings_op_mainport;
|
||||||
|
HwSettingsOP_MainPortGet(&hwsettings_op_mainport);
|
||||||
|
|
||||||
|
switch (hwsettings_op_mainport) {
|
||||||
|
case HWSETTINGS_OP_MAINPORT_DISABLED:
|
||||||
|
break;
|
||||||
|
case HWSETTINGS_OP_MAINPORT_TELEMETRY:
|
||||||
#if defined(PIOS_INCLUDE_TELEMETRY_RF)
|
#if defined(PIOS_INCLUDE_TELEMETRY_RF)
|
||||||
{
|
{
|
||||||
uint32_t pios_usart_telem_rf_id;
|
uint32_t pios_usart_telem_rf_id;
|
||||||
if (PIOS_USART_Init(&pios_usart_telem_rf_id, &pios_usart_telem_cfg)) {
|
if (PIOS_USART_Init(&pios_usart_telem_rf_id, &pios_usart_telem_cfg)) {
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_RX_BUF_LEN);
|
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_RX_BUF_LEN);
|
||||||
uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_TX_BUF_LEN);
|
uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_TX_BUF_LEN);
|
||||||
PIOS_Assert(rx_buffer);
|
PIOS_Assert(rx_buffer);
|
||||||
PIOS_Assert(tx_buffer);
|
PIOS_Assert(tx_buffer);
|
||||||
if (PIOS_COM_Init(&pios_com_telem_rf_id, &pios_usart_com_driver, pios_usart_telem_rf_id,
|
if (PIOS_COM_Init(&pios_com_telem_rf_id, &pios_usart_com_driver, pios_usart_telem_rf_id,
|
||||||
rx_buffer, PIOS_COM_TELEM_RF_RX_BUF_LEN,
|
rx_buffer, PIOS_COM_TELEM_RF_RX_BUF_LEN,
|
||||||
tx_buffer, PIOS_COM_TELEM_RF_TX_BUF_LEN)) {
|
tx_buffer, PIOS_COM_TELEM_RF_TX_BUF_LEN)) {
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_TELEMETRY_RF */
|
#endif /* PIOS_INCLUDE_TELEMETRY_RF */
|
||||||
|
break;
|
||||||
#if defined(PIOS_INCLUDE_GPS)
|
|
||||||
{
|
|
||||||
uint32_t pios_usart_gps_id;
|
|
||||||
if (PIOS_USART_Init(&pios_usart_gps_id, &pios_usart_gps_cfg)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_GPS_RX_BUF_LEN);
|
|
||||||
PIOS_Assert(rx_buffer);
|
|
||||||
if (PIOS_COM_Init(&pios_com_gps_id, &pios_usart_com_driver, pios_usart_gps_id,
|
|
||||||
rx_buffer, PIOS_COM_GPS_RX_BUF_LEN,
|
|
||||||
NULL, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* PIOS_INCLUDE_GPS */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PIOS_Servo_Init();
|
/* Configure the flexi port */
|
||||||
|
uint8_t hwsettings_op_flexiport;
|
||||||
|
HwSettingsOP_FlexiPortGet(&hwsettings_op_flexiport);
|
||||||
|
|
||||||
|
switch (hwsettings_op_flexiport) {
|
||||||
|
case HWSETTINGS_OP_FLEXIPORT_DISABLED:
|
||||||
|
break;
|
||||||
|
case HWSETTINGS_OP_FLEXIPORT_GPS:
|
||||||
|
#if defined(PIOS_INCLUDE_GPS)
|
||||||
|
{
|
||||||
|
uint32_t pios_usart_gps_id;
|
||||||
|
if (PIOS_USART_Init(&pios_usart_gps_id, &pios_usart_gps_cfg)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_GPS_RX_BUF_LEN);
|
||||||
|
PIOS_Assert(rx_buffer);
|
||||||
|
if (PIOS_COM_Init(&pios_com_gps_id, &pios_usart_com_driver, pios_usart_gps_id,
|
||||||
|
rx_buffer, PIOS_COM_GPS_RX_BUF_LEN,
|
||||||
|
NULL, 0)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* PIOS_INCLUDE_GPS */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PIOS_DEBUG_ENABLE_DEBUG_PINS
|
||||||
|
PIOS_Servo_Init(&pios_servo_cfg);
|
||||||
|
#endif /* PIOS_DEBUG_ENABLE_DEBUG_PINS */
|
||||||
|
|
||||||
PIOS_ADC_Init();
|
PIOS_ADC_Init();
|
||||||
PIOS_GPIO_Init();
|
PIOS_GPIO_Init();
|
||||||
|
|
||||||
/* Configure the selected receiver */
|
/* Configure the rcvr port */
|
||||||
uint8_t manualcontrolsettings_inputmode;
|
uint8_t hwsettings_rcvrport;
|
||||||
ManualControlSettingsInitialize();
|
HwSettingsOP_RcvrPortGet(&hwsettings_rcvrport);
|
||||||
ManualControlSettingsInputModeGet(&manualcontrolsettings_inputmode);
|
|
||||||
|
|
||||||
switch (manualcontrolsettings_inputmode) {
|
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_PWM:
|
switch (hwsettings_rcvrport) {
|
||||||
#if defined(PIOS_INCLUDE_PWM)
|
case HWSETTINGS_OP_RCVRPORT_DISABLED:
|
||||||
#if (PIOS_PWM_NUM_INPUTS > PIOS_RCVR_MAX_CHANNELS)
|
break;
|
||||||
#error More receiver inputs than available devices
|
case HWSETTINGS_OP_RCVRPORT_DEBUG:
|
||||||
#endif
|
/* Not supported yet */
|
||||||
PIOS_PWM_Init();
|
break;
|
||||||
uint32_t pios_pwm_rcvr_id;
|
case HWSETTINGS_OP_RCVRPORT_SPEKTRUM1:
|
||||||
if (PIOS_RCVR_Init(&pios_pwm_rcvr_id, &pios_pwm_rcvr_driver, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < PIOS_PWM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
|
||||||
i++) {
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_pwm_rcvr_id;
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_PWM */
|
|
||||||
break;
|
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_PPM:
|
|
||||||
#if defined(PIOS_INCLUDE_PPM)
|
|
||||||
#if (PIOS_PPM_NUM_INPUTS > PIOS_RCVR_MAX_CHANNELS)
|
|
||||||
#error More receiver inputs than available devices
|
|
||||||
#endif
|
|
||||||
PIOS_PPM_Init();
|
|
||||||
uint32_t pios_ppm_rcvr_id;
|
|
||||||
if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < PIOS_PPM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
|
||||||
i++) {
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_ppm_rcvr_id;
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
|
||||||
#endif /* PIOS_INCLUDE_PPM */
|
|
||||||
break;
|
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_SPEKTRUM:
|
|
||||||
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
||||||
#if (PIOS_SPEKTRUM_NUM_INPUTS > PIOS_RCVR_MAX_CHANNELS)
|
{
|
||||||
#error More receiver inputs than available devices
|
uint32_t pios_usart_spektrum_id;
|
||||||
#endif
|
if (PIOS_USART_Init(&pios_usart_spektrum_id, &pios_usart_spektrum_cfg)) {
|
||||||
{
|
PIOS_Assert(0);
|
||||||
uint32_t pios_usart_spektrum_id;
|
|
||||||
if (PIOS_USART_Init(&pios_usart_spektrum_id, &pios_usart_spektrum_cfg)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pios_spektrum_id;
|
|
||||||
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, false)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pios_spektrum_rcvr_id;
|
|
||||||
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, 0)) {
|
|
||||||
PIOS_Assert(0);
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < PIOS_SPEKTRUM_NUM_INPUTS && pios_rcvr_max_channel < NELEMENTS(pios_rcvr_channel_to_id_map);
|
|
||||||
i++) {
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].id = pios_spektrum_rcvr_id;
|
|
||||||
pios_rcvr_channel_to_id_map[pios_rcvr_max_channel].channel = i;
|
|
||||||
pios_rcvr_max_channel++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pios_spektrum_id;
|
||||||
|
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, false)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pios_spektrum_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, pios_spektrum_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1] = pios_spektrum_rcvr_id;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case MANUALCONTROLSETTINGS_INPUTMODE_SBUS:
|
case HWSETTINGS_OP_RCVRPORT_PWM:
|
||||||
#if defined(PIOS_INCLUDE_SBUS)
|
#if defined(PIOS_INCLUDE_PWM)
|
||||||
#error SBUS NOT ON OP YET
|
{
|
||||||
#endif /* PIOS_INCLUDE_SBUS */
|
uint32_t pios_pwm_id;
|
||||||
break;
|
PIOS_PWM_Init(&pios_pwm_id, &pios_pwm_cfg);
|
||||||
|
|
||||||
|
uint32_t pios_pwm_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_pwm_rcvr_id, &pios_pwm_rcvr_driver, pios_pwm_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_PWM] = pios_pwm_rcvr_id;
|
||||||
|
}
|
||||||
|
#endif /* PIOS_INCLUDE_PWM */
|
||||||
|
break;
|
||||||
|
case HWSETTINGS_OP_RCVRPORT_PPM:
|
||||||
|
#if defined(PIOS_INCLUDE_PPM)
|
||||||
|
{
|
||||||
|
uint32_t pios_ppm_id;
|
||||||
|
PIOS_PPM_Init(&pios_ppm_id, &pios_ppm_cfg);
|
||||||
|
|
||||||
|
uint32_t pios_ppm_rcvr_id;
|
||||||
|
if (PIOS_RCVR_Init(&pios_ppm_rcvr_id, &pios_ppm_rcvr_driver, pios_ppm_id)) {
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_PPM] = pios_ppm_rcvr_id;
|
||||||
|
}
|
||||||
|
#endif /* PIOS_INCLUDE_PPM */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_USB_HID)
|
#if defined(PIOS_INCLUDE_USB_HID)
|
||||||
|
@ -70,6 +70,7 @@ UAVOBJSRCFILENAMES += velocitydesired
|
|||||||
UAVOBJSRCFILENAMES += watchdogstatus
|
UAVOBJSRCFILENAMES += watchdogstatus
|
||||||
UAVOBJSRCFILENAMES += flightstatus
|
UAVOBJSRCFILENAMES += flightstatus
|
||||||
UAVOBJSRCFILENAMES += hwsettings
|
UAVOBJSRCFILENAMES += hwsettings
|
||||||
|
UAVOBJSRCFILENAMES += receiveractivity
|
||||||
UAVOBJSRCFILENAMES += cameradesired
|
UAVOBJSRCFILENAMES += cameradesired
|
||||||
UAVOBJSRCFILENAMES += camerastabsettings
|
UAVOBJSRCFILENAMES += camerastabsettings
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
* and we cannot define a linker script for each of them atm
|
* and we cannot define a linker script for each of them atm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_INITCALL(ifn, iparam, sfn, sparam, flags)
|
#define MODULE_INITCALL(ifn, sfn)
|
||||||
|
|
||||||
#define MODULE_TASKCREATE_ALL
|
#define MODULE_TASKCREATE_ALL
|
||||||
|
|
||||||
|
@ -206,22 +206,25 @@ extern uint32_t pios_com_telem_usb_id;
|
|||||||
// PIOS_RCVR
|
// PIOS_RCVR
|
||||||
// See also pios_board.c
|
// See also pios_board.c
|
||||||
//------------------------
|
//------------------------
|
||||||
#define PIOS_RCVR_MAX_DEVS 1
|
#define PIOS_RCVR_MAX_DEVS 3
|
||||||
#define PIOS_RCVR_MAX_CHANNELS 12
|
#define PIOS_RCVR_MAX_CHANNELS 12
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver PPM input
|
// Receiver PPM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_PPM_MAX_DEVS 1
|
||||||
#define PIOS_PPM_NUM_INPUTS 12
|
#define PIOS_PPM_NUM_INPUTS 12
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver PWM input
|
// Receiver PWM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_PWM_MAX_DEVS 1
|
||||||
#define PIOS_PWM_NUM_INPUTS 6
|
#define PIOS_PWM_NUM_INPUTS 6
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver SPEKTRUM input
|
// Receiver SPEKTRUM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_SPEKTRUM_MAX_DEVS 2
|
||||||
#define PIOS_SPEKTRUM_NUM_INPUTS 12
|
#define PIOS_SPEKTRUM_NUM_INPUTS 12
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@ -230,6 +233,11 @@ extern uint32_t pios_com_telem_usb_id;
|
|||||||
#define PIOS_SERVO_UPDATE_HZ 50
|
#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_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */
|
||||||
|
|
||||||
|
//--------------------------
|
||||||
|
// Timer controller settings
|
||||||
|
//--------------------------
|
||||||
|
#define PIOS_TIM_MAX_DEVS 3
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// GPIO
|
// GPIO
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
@ -185,16 +185,19 @@ extern uint32_t pios_com_aux_id;
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver PPM input
|
// Receiver PPM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_PPM_MAX_DEVS 1
|
||||||
#define PIOS_PPM_NUM_INPUTS 12
|
#define PIOS_PPM_NUM_INPUTS 12
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver PWM input
|
// Receiver PWM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_PWM_MAX_DEVS 1
|
||||||
#define PIOS_PWM_NUM_INPUTS 8
|
#define PIOS_PWM_NUM_INPUTS 8
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Receiver SPEKTRUM input
|
// Receiver SPEKTRUM input
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
#define PIOS_SPEKTRUM_MAX_DEVS 1
|
||||||
#define PIOS_SPEKTRUM_NUM_INPUTS 12
|
#define PIOS_SPEKTRUM_NUM_INPUTS 12
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@ -203,6 +206,11 @@ extern uint32_t pios_com_aux_id;
|
|||||||
#define PIOS_SERVO_UPDATE_HZ 50
|
#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_SERVOS_INITIAL_POSITION 0 /* dont want to start motors, have no pulse till settings loaded */
|
||||||
|
|
||||||
|
//--------------------------
|
||||||
|
// Timer controller settings
|
||||||
|
//--------------------------
|
||||||
|
#define PIOS_TIM_MAX_DEVS 3
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// ADC
|
// ADC
|
||||||
// PIOS_ADC_PinGet(0) = Temperature Sensor (On-board)
|
// PIOS_ADC_PinGet(0) = Temperature Sensor (On-board)
|
||||||
|
@ -67,12 +67,12 @@ static bool PIOS_COM_validate(struct pios_com_dev * com_dev)
|
|||||||
return (com_dev && (com_dev->magic == PIOS_COM_DEV_MAGIC));
|
return (com_dev && (com_dev->magic == PIOS_COM_DEV_MAGIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_com_dev * PIOS_COM_alloc(void)
|
static struct pios_com_dev * PIOS_COM_alloc(void)
|
||||||
{
|
{
|
||||||
struct pios_com_dev * com_dev;
|
struct pios_com_dev * com_dev;
|
||||||
|
|
||||||
com_dev = (struct pios_com_dev *)malloc(sizeof(*com_dev));
|
com_dev = (struct pios_com_dev *)pvPortMalloc(sizeof(*com_dev));
|
||||||
if (!com_dev) return (NULL);
|
if (!com_dev) return (NULL);
|
||||||
|
|
||||||
com_dev->magic = PIOS_COM_DEV_MAGIC;
|
com_dev->magic = PIOS_COM_DEV_MAGIC;
|
||||||
|
75
flight/PiOS/Common/pios_gcsrcvr.c
Normal file
75
flight/PiOS/Common/pios_gcsrcvr.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||||
|
* @{
|
||||||
|
* @addtogroup PIOS_GCSRCVR GCS Receiver Input Functions
|
||||||
|
* @brief Code to read the channels within the GCS Receiver UAVObject
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file pios_gcsrcvr.c
|
||||||
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @brief GCS Input functions (STM32 dependent)
|
||||||
|
* @see The GNU Public License (GPL) Version 3
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Project Includes */
|
||||||
|
#include "pios.h"
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_GCSRCVR)
|
||||||
|
|
||||||
|
#include "pios_gcsrcvr_priv.h"
|
||||||
|
|
||||||
|
static GCSReceiverData gcsreceiverdata;
|
||||||
|
|
||||||
|
/* Provide a RCVR driver */
|
||||||
|
static int32_t PIOS_GCSRCVR_Get(uint32_t rcvr_id, uint8_t channel);
|
||||||
|
|
||||||
|
const struct pios_rcvr_driver pios_gcsrcvr_rcvr_driver = {
|
||||||
|
.read = PIOS_GCSRCVR_Get,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gcsreceiver_updated(UAVObjEvent * ev)
|
||||||
|
{
|
||||||
|
if (ev->obj == GCSReceiverHandle()) {
|
||||||
|
GCSReceiverGet(&gcsreceiverdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PIOS_GCSRCVR_Init(void)
|
||||||
|
{
|
||||||
|
/* Register uavobj callback */
|
||||||
|
GCSReceiverConnectCallback (gcsreceiver_updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t PIOS_GCSRCVR_Get(uint32_t rcvr_id, uint8_t channel)
|
||||||
|
{
|
||||||
|
if (channel >= GCSRECEIVER_CHANNEL_NUMELEM) {
|
||||||
|
/* channel is out of range */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (gcsreceiverdata.Channel[channel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
@ -20,12 +20,12 @@ static bool PIOS_RCVR_validate(struct pios_rcvr_dev * rcvr_dev)
|
|||||||
return (rcvr_dev->magic == PIOS_RCVR_DEV_MAGIC);
|
return (rcvr_dev->magic == PIOS_RCVR_DEV_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_rcvr_dev * PIOS_RCVR_alloc(void)
|
static struct pios_rcvr_dev * PIOS_RCVR_alloc(void)
|
||||||
{
|
{
|
||||||
struct pios_rcvr_dev * rcvr_dev;
|
struct pios_rcvr_dev * rcvr_dev;
|
||||||
|
|
||||||
rcvr_dev = (struct pios_rcvr_dev *)malloc(sizeof(*rcvr_dev));
|
rcvr_dev = (struct pios_rcvr_dev *)pvPortMalloc(sizeof(*rcvr_dev));
|
||||||
if (!rcvr_dev) return (NULL);
|
if (!rcvr_dev) return (NULL);
|
||||||
|
|
||||||
rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC;
|
rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC;
|
||||||
@ -76,8 +76,26 @@ out_fail:
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads an input channel from the appropriate driver
|
||||||
|
* @param[in] rcvr_id driver to read from
|
||||||
|
* @param[in] channel channel to read
|
||||||
|
* @returns Unitless input value
|
||||||
|
* @retval PIOS_RCVR_TIMEOUT indicates a failsafe or timeout from that channel
|
||||||
|
* @retval PIOS_RCVR_INVALID invalid channel for this driver (usually out of range supported)
|
||||||
|
* @retval PIOS_RCVR_NODRIVER driver was not initialized
|
||||||
|
*/
|
||||||
int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel)
|
int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel)
|
||||||
{
|
{
|
||||||
|
// Publicly facing API uses channel 1 for first channel
|
||||||
|
if(channel == 0)
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
|
else
|
||||||
|
channel--;
|
||||||
|
|
||||||
|
if (rcvr_id == 0)
|
||||||
|
return PIOS_RCVR_NODRIVER;
|
||||||
|
|
||||||
struct pios_rcvr_dev * rcvr_dev = (struct pios_rcvr_dev *)rcvr_id;
|
struct pios_rcvr_dev * rcvr_dev = (struct pios_rcvr_dev *)rcvr_id;
|
||||||
|
|
||||||
if (!PIOS_RCVR_validate(rcvr_dev)) {
|
if (!PIOS_RCVR_validate(rcvr_dev)) {
|
||||||
|
@ -1025,12 +1025,12 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void TIM_DeInit(TIM_TypeDef* TIMx);
|
void TIM_DeInit(TIM_TypeDef* TIMx);
|
||||||
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
|
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, const TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
|
||||||
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
|
void TIM_OC1Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct);
|
||||||
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
|
void TIM_OC2Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct);
|
||||||
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
|
void TIM_OC3Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct);
|
||||||
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
|
void TIM_OC4Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct);
|
||||||
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
|
void TIM_ICInit(TIM_TypeDef* TIMx, const TIM_ICInitTypeDef* TIM_ICInitStruct);
|
||||||
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
|
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
|
||||||
void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct);
|
void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct);
|
||||||
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
|
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
|
||||||
|
@ -221,7 +221,7 @@ void TIM_DeInit(TIM_TypeDef* TIMx)
|
|||||||
* structure that contains the configuration information for the specified TIM peripheral.
|
* structure that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
|
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, const TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
|
||||||
{
|
{
|
||||||
uint16_t tmpcr1 = 0;
|
uint16_t tmpcr1 = 0;
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseIn
|
|||||||
* that contains the configuration information for the specified TIM peripheral.
|
* that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
void TIM_OC1Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct)
|
||||||
{
|
{
|
||||||
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
|||||||
* that contains the configuration information for the specified TIM peripheral.
|
* that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
void TIM_OC2Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct)
|
||||||
{
|
{
|
||||||
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
|||||||
* that contains the configuration information for the specified TIM peripheral.
|
* that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
void TIM_OC3Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct)
|
||||||
{
|
{
|
||||||
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
||||||
|
|
||||||
@ -518,7 +518,7 @@ void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
|||||||
* that contains the configuration information for the specified TIM peripheral.
|
* that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
void TIM_OC4Init(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct)
|
||||||
{
|
{
|
||||||
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
|
||||||
|
|
||||||
@ -582,7 +582,7 @@ void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
|
|||||||
* that contains the configuration information for the specified TIM peripheral.
|
* that contains the configuration information for the specified TIM peripheral.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
|
void TIM_ICInit(TIM_TypeDef* TIMx, const TIM_ICInitTypeDef* TIM_ICInitStruct)
|
||||||
{
|
{
|
||||||
/* Check the parameters */
|
/* Check the parameters */
|
||||||
assert_param(IS_TIM_CHANNEL(TIM_ICInitStruct->TIM_Channel));
|
assert_param(IS_TIM_CHANNEL(TIM_ICInitStruct->TIM_Channel));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* This is the size of the stack for all FreeRTOS IRQs */
|
/* This is the size of the stack for all FreeRTOS IRQs */
|
||||||
_irq_stack_size = 0x180;
|
_irq_stack_size = 0x1A0;
|
||||||
/* This is the size of the stack for early init: life span is until scheduler starts */
|
/* This is the size of the stack for early init: life span is until scheduler starts */
|
||||||
_init_stack_size = 0x100;
|
_init_stack_size = 0x100;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* This is the size of the stack for early init and for all FreeRTOS IRQs */
|
/* This is the size of the stack for early init and for all FreeRTOS IRQs */
|
||||||
_irq_stack_size = 0x400;
|
_irq_stack_size = 0x800;
|
||||||
/* This is the size of the stack for early init: life span is until scheduler starts */
|
/* This is the size of the stack for early init: life span is until scheduler starts */
|
||||||
_init_stack_size = 0x400;
|
_init_stack_size = 0x800;
|
||||||
|
|
||||||
/* Check valid alignment for VTOR */
|
/* Check valid alignment for VTOR */
|
||||||
ASSERT(ORIGIN(FLASH) == ALIGN(ORIGIN(FLASH), 0x80), "Start of memory region flash not aligned for startup vector table");
|
ASSERT(ORIGIN(FLASH) == ALIGN(ORIGIN(FLASH), 0x80), "Start of memory region flash not aligned for startup vector table");
|
||||||
|
@ -34,39 +34,41 @@
|
|||||||
// Global variables
|
// Global variables
|
||||||
const char *PIOS_DEBUG_AssertMsg = "ASSERT FAILED";
|
const char *PIOS_DEBUG_AssertMsg = "ASSERT FAILED";
|
||||||
|
|
||||||
#include <pios_servo_priv.h>
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
extern const struct pios_servo_channel pios_servo_channels[];
|
static const struct pios_tim_channel * debug_channels;
|
||||||
#define PIOS_SERVO_GPIO_PORT_1TO4 pios_servo_channels[0].port
|
static uint8_t debug_num_channels;
|
||||||
#define PIOS_SERVO_GPIO_PORT_5TO8 pios_servo_channels[4].port
|
#endif /* PIOS_ENABLE_DEBUG_PINS */
|
||||||
#define PIOS_SERVO_GPIO_PIN_1 pios_servo_channels[0].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_2 pios_servo_channels[1].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_3 pios_servo_channels[2].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_4 pios_servo_channels[3].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_5 pios_servo_channels[4].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_6 pios_servo_channels[5].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_7 pios_servo_channels[6].pin
|
|
||||||
#define PIOS_SERVO_GPIO_PIN_8 pios_servo_channels[7].pin
|
|
||||||
/* Private Function Prototypes */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise Debug-features
|
* Initialise Debug-features
|
||||||
*/
|
*/
|
||||||
void PIOS_DEBUG_Init(void)
|
void PIOS_DEBUG_Init(const struct pios_tim_channel * channels, uint8_t num_channels)
|
||||||
{
|
{
|
||||||
#ifdef PIOS_ENABLE_DEBUG_PINS
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
// Initialise Servo pins as standard output pins
|
PIOS_Assert(channels);
|
||||||
GPIO_InitTypeDef GPIO_InitStructure;
|
PIOS_Assert(num_channels);
|
||||||
GPIO_StructInit(&GPIO_InitStructure);
|
|
||||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
||||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
||||||
GPIO_InitStructure.GPIO_Pin = PIOS_SERVO_GPIO_PIN_1 | PIOS_SERVO_GPIO_PIN_2 | PIOS_SERVO_GPIO_PIN_3 | PIOS_SERVO_GPIO_PIN_4;
|
|
||||||
GPIO_Init(PIOS_SERVO_GPIO_PORT_1TO4, &GPIO_InitStructure);
|
|
||||||
GPIO_InitStructure.GPIO_Pin = PIOS_SERVO_GPIO_PIN_5 | PIOS_SERVO_GPIO_PIN_6 | PIOS_SERVO_GPIO_PIN_7 | PIOS_SERVO_GPIO_PIN_8;
|
|
||||||
GPIO_Init(PIOS_SERVO_GPIO_PORT_5TO8, &GPIO_InitStructure);
|
|
||||||
|
|
||||||
// Drive all pins low
|
/* Store away the GPIOs we've been given */
|
||||||
PIOS_SERVO_GPIO_PORT_1TO4->BRR = PIOS_SERVO_GPIO_PIN_1 | PIOS_SERVO_GPIO_PIN_2 | PIOS_SERVO_GPIO_PIN_3 | PIOS_SERVO_GPIO_PIN_4;
|
debug_channels = channels;
|
||||||
PIOS_SERVO_GPIO_PORT_5TO8->BRR = PIOS_SERVO_GPIO_PIN_5 | PIOS_SERVO_GPIO_PIN_6 | PIOS_SERVO_GPIO_PIN_7 | PIOS_SERVO_GPIO_PIN_8;
|
debug_num_channels = num_channels;
|
||||||
|
|
||||||
|
/* Configure the GPIOs we've been given */
|
||||||
|
for (uint8_t i = 0; i < num_channels; i++) {
|
||||||
|
const struct pios_tim_channel * chan = &channels[i];
|
||||||
|
|
||||||
|
// Initialise pins as standard output pins
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
|
GPIO_StructInit(&GPIO_InitStructure);
|
||||||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStructure.GPIO_Pin = chan->init->GPIO_Pin;
|
||||||
|
|
||||||
|
/* Initialize the GPIO */
|
||||||
|
GPIO_Init(chan->init->port, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
/* Set the pin low */
|
||||||
|
GPIO_WriteBit(chan->init->port, chan->init->GPIO_Pin, Bit_RESET);
|
||||||
|
}
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,14 +76,17 @@ void PIOS_DEBUG_Init(void)
|
|||||||
* Set debug-pin high
|
* Set debug-pin high
|
||||||
* \param pin 0 for S1 output
|
* \param pin 0 for S1 output
|
||||||
*/
|
*/
|
||||||
void PIOS_DEBUG_PinHigh(uint8_t Pin)
|
void PIOS_DEBUG_PinHigh(uint8_t pin)
|
||||||
{
|
{
|
||||||
#ifdef PIOS_ENABLE_DEBUG_PINS
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
if (Pin < 4) {
|
if (!debug_channels || pin >= debug_num_channels) {
|
||||||
PIOS_SERVO_GPIO_PORT_1TO4->BSRR = (PIOS_SERVO_GPIO_PIN_1 << Pin);
|
return;
|
||||||
} else if (Pin <= 7) {
|
|
||||||
PIOS_SERVO_GPIO_PORT_5TO8->BSRR = (PIOS_SERVO_GPIO_PIN_5 << (Pin - 4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct pios_tim_channel * chan = &debug_channels[pin];
|
||||||
|
|
||||||
|
GPIO_WriteBit(chan->init->port, chan->init->GPIO_Pin, Bit_Set);
|
||||||
|
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,14 +94,17 @@ void PIOS_DEBUG_PinHigh(uint8_t Pin)
|
|||||||
* Set debug-pin low
|
* Set debug-pin low
|
||||||
* \param pin 0 for S1 output
|
* \param pin 0 for S1 output
|
||||||
*/
|
*/
|
||||||
void PIOS_DEBUG_PinLow(uint8_t Pin)
|
void PIOS_DEBUG_PinLow(uint8_t pin)
|
||||||
{
|
{
|
||||||
#ifdef PIOS_ENABLE_DEBUG_PINS
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
if (Pin < 4) {
|
if (!debug_channels || pin >= debug_num_channels) {
|
||||||
PIOS_SERVO_GPIO_PORT_1TO4->BRR = (PIOS_SERVO_GPIO_PIN_1 << Pin);
|
return;
|
||||||
} else if (Pin <= 7) {
|
|
||||||
PIOS_SERVO_GPIO_PORT_5TO8->BRR = (PIOS_SERVO_GPIO_PIN_5 << (Pin - 4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct pios_tim_channel * chan = &debug_channels[pin];
|
||||||
|
|
||||||
|
GPIO_WriteBit(chan->init->port, chan->init->GPIO_Pin, Bit_RESET);
|
||||||
|
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +112,22 @@ void PIOS_DEBUG_PinLow(uint8_t Pin)
|
|||||||
void PIOS_DEBUG_PinValue8Bit(uint8_t value)
|
void PIOS_DEBUG_PinValue8Bit(uint8_t value)
|
||||||
{
|
{
|
||||||
#ifdef PIOS_ENABLE_DEBUG_PINS
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
|
if (!debug_channels) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t bsrr_l = ( ((~value)&0x0F)<<(16+6) ) | ((value & 0x0F)<<6);
|
uint32_t bsrr_l = ( ((~value)&0x0F)<<(16+6) ) | ((value & 0x0F)<<6);
|
||||||
uint32_t bsrr_h = ( ((~value)&0xF0)<<(16+6-4) ) | ((value & 0xF0)<<(6-4));
|
uint32_t bsrr_h = ( ((~value)&0xF0)<<(16+6-4) ) | ((value & 0xF0)<<(6-4));
|
||||||
|
|
||||||
PIOS_IRQ_Disable();
|
PIOS_IRQ_Disable();
|
||||||
PIOS_SERVO_GPIO_PORT_1TO4->BSRR = bsrr_l;
|
|
||||||
PIOS_SERVO_GPIO_PORT_5TO8->BSRR = bsrr_h;
|
/*
|
||||||
|
* This is sketchy since it assumes a particular ordering
|
||||||
|
* and bitwise layout of the channels provided to the debug code.
|
||||||
|
*/
|
||||||
|
debug_channels[0].init.port->BSRR = bsrr_l;
|
||||||
|
debug_channels[4].init.port->BSRR = bsrr_h;
|
||||||
|
|
||||||
PIOS_IRQ_Enable();
|
PIOS_IRQ_Enable();
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||||
}
|
}
|
||||||
@ -116,8 +135,16 @@ void PIOS_DEBUG_PinValue8Bit(uint8_t value)
|
|||||||
void PIOS_DEBUG_PinValue4BitL(uint8_t value)
|
void PIOS_DEBUG_PinValue4BitL(uint8_t value)
|
||||||
{
|
{
|
||||||
#ifdef PIOS_ENABLE_DEBUG_PINS
|
#ifdef PIOS_ENABLE_DEBUG_PINS
|
||||||
|
if (!debug_channels) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is sketchy since it assumes a particular ordering
|
||||||
|
* and bitwise layout of the channels provided to the debug code.
|
||||||
|
*/
|
||||||
uint32_t bsrr_l = ((~(value & 0x0F)<<(16+6))) | ((value & 0x0F)<<6);
|
uint32_t bsrr_l = ((~(value & 0x0F)<<(16+6))) | ((value & 0x0F)<<6);
|
||||||
PIOS_SERVO_GPIO_PORT_1TO4->BSRR = bsrr_l;
|
debug_channels[0].init.port->BSRR = bsrr_l;
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,12 +823,12 @@ static bool PIOS_I2C_validate(struct pios_i2c_adapter * i2c_adapter)
|
|||||||
return (i2c_adapter->magic == PIOS_I2C_DEV_MAGIC);
|
return (i2c_adapter->magic == PIOS_I2C_DEV_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_i2c_dev * PIOS_I2C_alloc(void)
|
static struct pios_i2c_adapter * PIOS_I2C_alloc(void)
|
||||||
{
|
{
|
||||||
struct pios_i2c_dev * i2c_adapter;
|
struct pios_i2c_adapter * i2c_adapter;
|
||||||
|
|
||||||
i2c_adapter = (struct pios_i2c_adapter *)malloc(sizeof(*i2c_adapter));
|
i2c_adapter = (struct pios_i2c_adapter *)pvPortMalloc(sizeof(*i2c_adapter));
|
||||||
if (!i2c_adapter) return(NULL);
|
if (!i2c_adapter) return(NULL);
|
||||||
|
|
||||||
i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
|
i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
|
||||||
|
@ -47,108 +47,139 @@ const struct pios_rcvr_driver pios_ppm_rcvr_driver = {
|
|||||||
#define PIOS_PPM_IN_MIN_SYNC_PULSE_US 3800 // microseconds
|
#define PIOS_PPM_IN_MIN_SYNC_PULSE_US 3800 // microseconds
|
||||||
#define PIOS_PPM_IN_MIN_CHANNEL_PULSE_US 750 // microseconds
|
#define PIOS_PPM_IN_MIN_CHANNEL_PULSE_US 750 // microseconds
|
||||||
#define PIOS_PPM_IN_MAX_CHANNEL_PULSE_US 2250 // microseconds
|
#define PIOS_PPM_IN_MAX_CHANNEL_PULSE_US 2250 // microseconds
|
||||||
#define PIOS_PPM_INPUT_INVALID 0
|
|
||||||
|
|
||||||
/* Local Variables */
|
/* Local Variables */
|
||||||
static TIM_ICInitTypeDef TIM_ICInitStructure;
|
static TIM_ICInitTypeDef TIM_ICInitStructure;
|
||||||
static uint8_t PulseIndex;
|
|
||||||
static uint32_t PreviousTime;
|
|
||||||
static uint32_t CurrentTime;
|
|
||||||
static uint32_t DeltaTime;
|
|
||||||
static uint32_t CaptureValue[PIOS_PPM_IN_MAX_NUM_CHANNELS];
|
|
||||||
static uint32_t CaptureValueNewFrame[PIOS_PPM_IN_MAX_NUM_CHANNELS];
|
|
||||||
static uint32_t LargeCounter;
|
|
||||||
static int8_t NumChannels;
|
|
||||||
static int8_t NumChannelsPrevFrame;
|
|
||||||
static uint8_t NumChannelCounter;
|
|
||||||
|
|
||||||
static uint8_t supv_timer = 0;
|
|
||||||
static bool Tracking;
|
|
||||||
static bool Fresh;
|
|
||||||
|
|
||||||
static void PIOS_PPM_Supervisor(uint32_t ppm_id);
|
static void PIOS_PPM_Supervisor(uint32_t ppm_id);
|
||||||
|
|
||||||
void PIOS_PPM_Init(void)
|
enum pios_ppm_dev_magic {
|
||||||
|
PIOS_PPM_DEV_MAGIC = 0xee014d8b,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_ppm_dev {
|
||||||
|
enum pios_ppm_dev_magic magic;
|
||||||
|
const struct pios_ppm_cfg * cfg;
|
||||||
|
|
||||||
|
uint8_t PulseIndex;
|
||||||
|
uint32_t PreviousTime;
|
||||||
|
uint32_t CurrentTime;
|
||||||
|
uint32_t DeltaTime;
|
||||||
|
uint32_t CaptureValue[PIOS_PPM_IN_MAX_NUM_CHANNELS];
|
||||||
|
uint32_t CaptureValueNewFrame[PIOS_PPM_IN_MAX_NUM_CHANNELS];
|
||||||
|
uint32_t LargeCounter;
|
||||||
|
int8_t NumChannels;
|
||||||
|
int8_t NumChannelsPrevFrame;
|
||||||
|
uint8_t NumChannelCounter;
|
||||||
|
|
||||||
|
uint8_t supv_timer;
|
||||||
|
bool Tracking;
|
||||||
|
bool Fresh;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool PIOS_PPM_validate(struct pios_ppm_dev * ppm_dev)
|
||||||
{
|
{
|
||||||
/* Flush counter variables */
|
return (ppm_dev->magic == PIOS_PPM_DEV_MAGIC);
|
||||||
int32_t i;
|
}
|
||||||
|
|
||||||
PulseIndex = 0;
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
PreviousTime = 0;
|
static struct pios_ppm_dev * PIOS_PPM_alloc(void)
|
||||||
CurrentTime = 0;
|
{
|
||||||
DeltaTime = 0;
|
struct pios_ppm_dev * ppm_dev;
|
||||||
LargeCounter = 0;
|
|
||||||
NumChannels = -1;
|
|
||||||
NumChannelsPrevFrame = -1;
|
|
||||||
NumChannelCounter = 0;
|
|
||||||
Tracking = FALSE;
|
|
||||||
Fresh = FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
ppm_dev = (struct pios_ppm_dev *)pvPortMalloc(sizeof(*ppm_dev));
|
||||||
CaptureValue[i] = 0;
|
if (!ppm_dev) return(NULL);
|
||||||
CaptureValueNewFrame[i] = 0;
|
|
||||||
|
ppm_dev->magic = PIOS_PPM_DEV_MAGIC;
|
||||||
|
return(ppm_dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct pios_ppm_dev pios_ppm_devs[PIOS_PPM_MAX_DEVS];
|
||||||
|
static uint8_t pios_ppm_num_devs;
|
||||||
|
static struct pios_ppm_dev * PIOS_PPM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_ppm_dev * ppm_dev;
|
||||||
|
|
||||||
|
if (pios_ppm_num_devs >= PIOS_PPM_MAX_DEVS) {
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
NVIC_InitTypeDef NVIC_InitStructure = pios_ppm_cfg.irq.init;
|
ppm_dev = &pios_ppm_devs[pios_ppm_num_devs++];
|
||||||
|
ppm_dev->magic = PIOS_PPM_DEV_MAGIC;
|
||||||
|
|
||||||
/* Enable appropriate clock to timer module */
|
return (ppm_dev);
|
||||||
switch((int32_t) pios_ppm_cfg.timer) {
|
}
|
||||||
case (int32_t)TIM1:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM2:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM3:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM4:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
|
||||||
break;
|
|
||||||
#ifdef STM32F10X_HD
|
|
||||||
case (int32_t)TIM5:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM6:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM7:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM8:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn;
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void PIOS_PPM_tim_overflow_cb (uint32_t id, uint32_t context, uint8_t channel, uint16_t count);
|
||||||
|
static void PIOS_PPM_tim_edge_cb (uint32_t id, uint32_t context, uint8_t channel, uint16_t count);
|
||||||
|
const static struct pios_tim_callbacks tim_callbacks = {
|
||||||
|
.overflow = PIOS_PPM_tim_overflow_cb,
|
||||||
|
.edge = PIOS_PPM_tim_edge_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int32_t PIOS_PPM_Init(uint32_t * ppm_id, const struct pios_ppm_cfg * cfg)
|
||||||
|
{
|
||||||
|
PIOS_DEBUG_Assert(ppm_id);
|
||||||
|
PIOS_DEBUG_Assert(cfg);
|
||||||
|
|
||||||
|
struct pios_ppm_dev * ppm_dev;
|
||||||
|
|
||||||
|
ppm_dev = (struct pios_ppm_dev *) PIOS_PPM_alloc();
|
||||||
|
if (!ppm_dev) goto out_fail;
|
||||||
|
|
||||||
|
/* Bind the configuration to the device instance */
|
||||||
|
ppm_dev->cfg = cfg;
|
||||||
|
|
||||||
|
/* Set up the state variables */
|
||||||
|
ppm_dev->PulseIndex = 0;
|
||||||
|
ppm_dev->PreviousTime = 0;
|
||||||
|
ppm_dev->CurrentTime = 0;
|
||||||
|
ppm_dev->DeltaTime = 0;
|
||||||
|
ppm_dev->LargeCounter = 0;
|
||||||
|
ppm_dev->NumChannels = -1;
|
||||||
|
ppm_dev->NumChannelsPrevFrame = -1;
|
||||||
|
ppm_dev->NumChannelCounter = 0;
|
||||||
|
ppm_dev->Tracking = FALSE;
|
||||||
|
ppm_dev->Fresh = FALSE;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
||||||
|
/* Flush counter variables */
|
||||||
|
ppm_dev->CaptureValue[i] = 0;
|
||||||
|
ppm_dev->CaptureValueNewFrame[i] = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Enable timer interrupts */
|
|
||||||
NVIC_Init(&NVIC_InitStructure);
|
|
||||||
|
|
||||||
/* Configure input pins */
|
uint32_t tim_id;
|
||||||
GPIO_InitTypeDef GPIO_InitStructure = pios_ppm_cfg.gpio_init;
|
if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, &tim_callbacks, (uint32_t)ppm_dev)) {
|
||||||
GPIO_Init(pios_ppm_cfg.port, &GPIO_InitStructure);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure timer for input capture */
|
/* Configure the channels to be in capture/compare mode */
|
||||||
TIM_ICInitStructure = pios_ppm_cfg.tim_ic_init;
|
for (uint8_t i = 0; i < cfg->num_channels; i++) {
|
||||||
TIM_ICInit(pios_ppm_cfg.timer, &TIM_ICInitStructure);
|
const struct pios_tim_channel * chan = &cfg->channels[i];
|
||||||
|
|
||||||
/* Configure timer clocks */
|
/* Configure timer for input capture */
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = pios_ppm_cfg.tim_base_init;
|
TIM_ICInitTypeDef TIM_ICInitStructure = cfg->tim_ic_init;
|
||||||
TIM_InternalClockConfig(pios_ppm_cfg.timer);
|
TIM_ICInitStructure.TIM_Channel = chan->timer_chan;
|
||||||
TIM_TimeBaseInit(pios_ppm_cfg.timer, &TIM_TimeBaseStructure);
|
TIM_ICInit(chan->timer, &TIM_ICInitStructure);
|
||||||
|
|
||||||
/* Enable the Capture Compare Interrupt Request */
|
/* Enable the Capture Compare Interrupt Request */
|
||||||
TIM_ITConfig(pios_ppm_cfg.timer, pios_ppm_cfg.ccr | TIM_IT_Update, ENABLE);
|
switch (chan->timer_chan) {
|
||||||
|
case TIM_Channel_1:
|
||||||
/* Enable timers */
|
TIM_ITConfig(chan->timer, TIM_IT_CC1 | TIM_IT_Update, ENABLE);
|
||||||
TIM_Cmd(pios_ppm_cfg.timer, ENABLE);
|
break;
|
||||||
|
case TIM_Channel_2:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC2 | TIM_IT_Update, ENABLE);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_3:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC3 | TIM_IT_Update, ENABLE);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_4:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC4 | TIM_IT_Update, ENABLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup local variable which stays in this scope */
|
/* Setup local variable which stays in this scope */
|
||||||
/* Doing this here and using a local variable saves doing it in the ISR */
|
/* Doing this here and using a local variable saves doing it in the ISR */
|
||||||
@ -156,9 +187,16 @@ void PIOS_PPM_Init(void)
|
|||||||
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
|
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
|
||||||
TIM_ICInitStructure.TIM_ICFilter = 0x0;
|
TIM_ICInitStructure.TIM_ICFilter = 0x0;
|
||||||
|
|
||||||
if (!PIOS_RTC_RegisterTickCallback(PIOS_PPM_Supervisor, 0)) {
|
if (!PIOS_RTC_RegisterTickCallback(PIOS_PPM_Supervisor, (uint32_t)ppm_dev)) {
|
||||||
PIOS_DEBUG_Assert(0);
|
PIOS_DEBUG_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*ppm_id = (uint32_t)ppm_dev;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
out_fail:
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,142 +207,146 @@ void PIOS_PPM_Init(void)
|
|||||||
*/
|
*/
|
||||||
static int32_t PIOS_PPM_Get(uint32_t rcvr_id, uint8_t channel)
|
static int32_t PIOS_PPM_Get(uint32_t rcvr_id, uint8_t channel)
|
||||||
{
|
{
|
||||||
/* Return error if channel not available */
|
struct pios_ppm_dev * ppm_dev = (struct pios_ppm_dev *)rcvr_id;
|
||||||
if (channel >= PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
|
||||||
return -1;
|
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||||
|
/* Invalid device specified */
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
}
|
}
|
||||||
return CaptureValue[channel];
|
|
||||||
|
if (channel >= PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
||||||
|
/* Channel out of range */
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
|
}
|
||||||
|
return ppm_dev->CaptureValue[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void PIOS_PPM_tim_overflow_cb (uint32_t tim_id, uint32_t context, uint8_t channel, uint16_t count)
|
||||||
* Handle TIMx global interrupt request
|
|
||||||
* Some work and testing still needed, need to detect start of frame and decode pulses
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void PIOS_PPM_irq_handler(void)
|
|
||||||
{
|
{
|
||||||
/* Timer Overflow Interrupt
|
struct pios_ppm_dev * ppm_dev = (struct pios_ppm_dev *)context;
|
||||||
* The time between timer overflows must be greater than the PPM
|
|
||||||
* frame period. If a full frame has not decoded in the between timer
|
|
||||||
* overflows then capture values should be cleared.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (TIM_GetITStatus(pios_ppm_cfg.timer, TIM_IT_Update) == SET) {
|
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||||
/* Clear TIMx overflow interrupt pending bit */
|
/* Invalid device specified */
|
||||||
TIM_ClearITPendingBit(pios_ppm_cfg.timer, TIM_IT_Update);
|
return;
|
||||||
|
|
||||||
/* If sharing a timer with a servo output the ARR register will
|
|
||||||
be set according to the PWM period. When timer reaches the
|
|
||||||
ARR value a timer overflow interrupt will fire. We use the
|
|
||||||
interrupt accumulate a 32-bit timer. */
|
|
||||||
LargeCounter = LargeCounter + pios_ppm_cfg.timer->ARR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal edge interrupt */
|
ppm_dev->LargeCounter += count;
|
||||||
if (TIM_GetITStatus(pios_ppm_cfg.timer, pios_ppm_cfg.ccr) == SET) {
|
|
||||||
PreviousTime = CurrentTime;
|
|
||||||
|
|
||||||
switch((int32_t) pios_ppm_cfg.ccr) {
|
return;
|
||||||
case (int32_t)TIM_IT_CC1:
|
}
|
||||||
CurrentTime = TIM_GetCapture1(pios_ppm_cfg.timer);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM_IT_CC2:
|
static void PIOS_PPM_tim_edge_cb (uint32_t tim_id, uint32_t context, uint8_t chan_idx, uint16_t count)
|
||||||
CurrentTime = TIM_GetCapture2(pios_ppm_cfg.timer);
|
{
|
||||||
break;
|
/* Recover our device context */
|
||||||
case (int32_t)TIM_IT_CC3:
|
struct pios_ppm_dev * ppm_dev = (struct pios_ppm_dev *)context;
|
||||||
CurrentTime = TIM_GetCapture3(pios_ppm_cfg.timer);
|
|
||||||
break;
|
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||||
case (int32_t)TIM_IT_CC4:
|
/* Invalid device specified */
|
||||||
CurrentTime = TIM_GetCapture4(pios_ppm_cfg.timer);
|
return;
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
if (chan_idx >= ppm_dev->cfg->num_channels) {
|
||||||
|
/* Channel out of range */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the last measurement out */
|
||||||
|
ppm_dev->PreviousTime = ppm_dev->CurrentTime;
|
||||||
|
|
||||||
|
/* Grab the new count */
|
||||||
|
ppm_dev->CurrentTime = count;
|
||||||
|
|
||||||
|
/* Convert to 32-bit timer result */
|
||||||
|
ppm_dev->CurrentTime += ppm_dev->LargeCounter;
|
||||||
|
|
||||||
|
/* Capture computation */
|
||||||
|
ppm_dev->DeltaTime = ppm_dev->CurrentTime - ppm_dev->PreviousTime;
|
||||||
|
|
||||||
|
ppm_dev->PreviousTime = ppm_dev->CurrentTime;
|
||||||
|
|
||||||
|
/* Sync pulse detection */
|
||||||
|
if (ppm_dev->DeltaTime > PIOS_PPM_IN_MIN_SYNC_PULSE_US) {
|
||||||
|
if (ppm_dev->PulseIndex == ppm_dev->NumChannelsPrevFrame
|
||||||
|
&& ppm_dev->PulseIndex >= PIOS_PPM_IN_MIN_NUM_CHANNELS
|
||||||
|
&& ppm_dev->PulseIndex <= PIOS_PPM_IN_MAX_NUM_CHANNELS)
|
||||||
|
{
|
||||||
|
/* If we see n simultaneous frames of the same
|
||||||
|
number of channels we save it as our frame size */
|
||||||
|
if (ppm_dev->NumChannelCounter < PIOS_PPM_STABLE_CHANNEL_COUNT)
|
||||||
|
ppm_dev->NumChannelCounter++;
|
||||||
|
else
|
||||||
|
ppm_dev->NumChannels = ppm_dev->PulseIndex;
|
||||||
|
} else {
|
||||||
|
ppm_dev->NumChannelCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear TIMx Capture compare interrupt pending bit */
|
/* Check if the last frame was well formed */
|
||||||
TIM_ClearITPendingBit(pios_ppm_cfg.timer, pios_ppm_cfg.ccr);
|
if (ppm_dev->PulseIndex == ppm_dev->NumChannels && ppm_dev->Tracking) {
|
||||||
|
/* The last frame was well formed */
|
||||||
/* Convert to 32-bit timer result */
|
for (uint32_t i = 0; i < ppm_dev->NumChannels; i++) {
|
||||||
CurrentTime = CurrentTime + LargeCounter;
|
ppm_dev->CaptureValue[i] = ppm_dev->CaptureValueNewFrame[i];
|
||||||
|
|
||||||
/* Capture computation */
|
|
||||||
DeltaTime = CurrentTime - PreviousTime;
|
|
||||||
|
|
||||||
PreviousTime = CurrentTime;
|
|
||||||
|
|
||||||
/* Sync pulse detection */
|
|
||||||
if (DeltaTime > PIOS_PPM_IN_MIN_SYNC_PULSE_US) {
|
|
||||||
if (PulseIndex == NumChannelsPrevFrame
|
|
||||||
&& PulseIndex >= PIOS_PPM_IN_MIN_NUM_CHANNELS
|
|
||||||
&& PulseIndex <= PIOS_PPM_IN_MAX_NUM_CHANNELS)
|
|
||||||
{
|
|
||||||
/* If we see n simultaneous frames of the same
|
|
||||||
number of channels we save it as our frame size */
|
|
||||||
if (NumChannelCounter < PIOS_PPM_STABLE_CHANNEL_COUNT)
|
|
||||||
NumChannelCounter++;
|
|
||||||
else
|
|
||||||
NumChannels = PulseIndex;
|
|
||||||
} else {
|
|
||||||
NumChannelCounter = 0;
|
|
||||||
}
|
}
|
||||||
|
for (uint32_t i = ppm_dev->NumChannels;
|
||||||
/* Check if the last frame was well formed */
|
i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
||||||
if (PulseIndex == NumChannels && Tracking) {
|
ppm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||||
/* The last frame was well formed */
|
|
||||||
for (uint32_t i = 0; i < NumChannels; i++) {
|
|
||||||
CaptureValue[i] = CaptureValueNewFrame[i];
|
|
||||||
}
|
|
||||||
for (uint32_t i = NumChannels;
|
|
||||||
i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
|
||||||
CaptureValue[i] = PIOS_PPM_INPUT_INVALID;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Fresh = TRUE;
|
ppm_dev->Fresh = TRUE;
|
||||||
Tracking = TRUE;
|
ppm_dev->Tracking = TRUE;
|
||||||
NumChannelsPrevFrame = PulseIndex;
|
ppm_dev->NumChannelsPrevFrame = ppm_dev->PulseIndex;
|
||||||
PulseIndex = 0;
|
ppm_dev->PulseIndex = 0;
|
||||||
|
|
||||||
/* We rely on the supervisor to set CaptureValue to invalid
|
/* We rely on the supervisor to set CaptureValue to invalid
|
||||||
if no valid frame is found otherwise we ride over it */
|
if no valid frame is found otherwise we ride over it */
|
||||||
|
|
||||||
} else if (Tracking) {
|
} else if (ppm_dev->Tracking) {
|
||||||
/* Valid pulse duration 0.75 to 2.5 ms*/
|
/* Valid pulse duration 0.75 to 2.5 ms*/
|
||||||
if (DeltaTime > PIOS_PPM_IN_MIN_CHANNEL_PULSE_US
|
if (ppm_dev->DeltaTime > PIOS_PPM_IN_MIN_CHANNEL_PULSE_US
|
||||||
&& DeltaTime < PIOS_PPM_IN_MAX_CHANNEL_PULSE_US
|
&& ppm_dev->DeltaTime < PIOS_PPM_IN_MAX_CHANNEL_PULSE_US
|
||||||
&& PulseIndex < PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
&& ppm_dev->PulseIndex < PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
||||||
|
|
||||||
CaptureValueNewFrame[PulseIndex] = DeltaTime;
|
ppm_dev->CaptureValueNewFrame[ppm_dev->PulseIndex] = ppm_dev->DeltaTime;
|
||||||
PulseIndex++;
|
ppm_dev->PulseIndex++;
|
||||||
} else {
|
} else {
|
||||||
/* Not a valid pulse duration */
|
/* Not a valid pulse duration */
|
||||||
Tracking = FALSE;
|
ppm_dev->Tracking = FALSE;
|
||||||
for (uint32_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS ; i++) {
|
for (uint32_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS ; i++) {
|
||||||
CaptureValueNewFrame[i] = PIOS_PPM_INPUT_INVALID;
|
ppm_dev->CaptureValueNewFrame[i] = PIOS_RCVR_TIMEOUT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PIOS_PPM_Supervisor(uint32_t ppm_id) {
|
static void PIOS_PPM_Supervisor(uint32_t ppm_id) {
|
||||||
|
/* Recover our device context */
|
||||||
|
struct pios_ppm_dev * ppm_dev = (struct pios_ppm_dev *)ppm_id;
|
||||||
|
|
||||||
|
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||||
|
/* Invalid device specified */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RTC runs at 625Hz so divide down the base rate so
|
* RTC runs at 625Hz so divide down the base rate so
|
||||||
* that this loop runs at 25Hz.
|
* that this loop runs at 25Hz.
|
||||||
*/
|
*/
|
||||||
if(++supv_timer < 25) {
|
if(++(ppm_dev->supv_timer) < 25) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
supv_timer = 0;
|
ppm_dev->supv_timer = 0;
|
||||||
|
|
||||||
if (!Fresh) {
|
if (!ppm_dev->Fresh) {
|
||||||
Tracking = FALSE;
|
ppm_dev->Tracking = FALSE;
|
||||||
|
|
||||||
for (int32_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS ; i++) {
|
for (int32_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS ; i++) {
|
||||||
CaptureValue[i] = PIOS_PPM_INPUT_INVALID;
|
ppm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||||
CaptureValueNewFrame[i] = PIOS_PPM_INPUT_INVALID;
|
ppm_dev->CaptureValueNewFrame[i] = PIOS_RCVR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fresh = FALSE;
|
ppm_dev->Fresh = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,96 +42,131 @@ const struct pios_rcvr_driver pios_pwm_rcvr_driver = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Local Variables */
|
/* Local Variables */
|
||||||
static uint8_t CaptureState[PIOS_PWM_NUM_INPUTS];
|
/* 100 ms timeout without updates on channels */
|
||||||
static uint16_t RiseValue[PIOS_PWM_NUM_INPUTS];
|
const static uint32_t PWM_SUPERVISOR_TIMEOUT = 100000;
|
||||||
static uint16_t FallValue[PIOS_PWM_NUM_INPUTS];
|
|
||||||
static uint32_t CaptureValue[PIOS_PWM_NUM_INPUTS];
|
|
||||||
|
|
||||||
static uint32_t CapCounter[PIOS_PWM_NUM_INPUTS];
|
enum pios_pwm_dev_magic {
|
||||||
|
PIOS_PWM_DEV_MAGIC = 0xab30293c,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_pwm_dev {
|
||||||
|
enum pios_pwm_dev_magic magic;
|
||||||
|
const struct pios_pwm_cfg * cfg;
|
||||||
|
|
||||||
|
uint8_t CaptureState[PIOS_PWM_NUM_INPUTS];
|
||||||
|
uint16_t RiseValue[PIOS_PWM_NUM_INPUTS];
|
||||||
|
uint16_t FallValue[PIOS_PWM_NUM_INPUTS];
|
||||||
|
uint32_t CaptureValue[PIOS_PWM_NUM_INPUTS];
|
||||||
|
uint32_t CapCounter[PIOS_PWM_NUM_INPUTS];
|
||||||
|
uint32_t us_since_update[PIOS_PWM_NUM_INPUTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool PIOS_PWM_validate(struct pios_pwm_dev * pwm_dev)
|
||||||
|
{
|
||||||
|
return (pwm_dev->magic == PIOS_PWM_DEV_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
|
static struct pios_pwm_dev * PIOS_PWM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_pwm_dev * pwm_dev;
|
||||||
|
|
||||||
|
pwm_dev = (struct pios_pwm_dev *)pvPortMalloc(sizeof(*pwm_dev));
|
||||||
|
if (!pwm_dev) return(NULL);
|
||||||
|
|
||||||
|
pwm_dev->magic = PIOS_PWM_DEV_MAGIC;
|
||||||
|
return(pwm_dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct pios_pwm_dev pios_pwm_devs[PIOS_PWM_MAX_DEVS];
|
||||||
|
static uint8_t pios_pwm_num_devs;
|
||||||
|
static struct pios_pwm_dev * PIOS_PWM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_pwm_dev * pwm_dev;
|
||||||
|
|
||||||
|
if (pios_pwm_num_devs >= PIOS_PWM_MAX_DEVS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_dev = &pios_pwm_devs[pios_pwm_num_devs++];
|
||||||
|
pwm_dev->magic = PIOS_PWM_DEV_MAGIC;
|
||||||
|
|
||||||
|
return (pwm_dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void PIOS_PWM_tim_overflow_cb (uint32_t id, uint32_t context, uint8_t channel, uint16_t count);
|
||||||
|
static void PIOS_PWM_tim_edge_cb (uint32_t id, uint32_t context, uint8_t channel, uint16_t count);
|
||||||
|
const static struct pios_tim_callbacks tim_callbacks = {
|
||||||
|
.overflow = PIOS_PWM_tim_overflow_cb,
|
||||||
|
.edge = PIOS_PWM_tim_edge_cb,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises all the pins
|
* Initialises all the pins
|
||||||
*/
|
*/
|
||||||
void PIOS_PWM_Init(void)
|
int32_t PIOS_PWM_Init(uint32_t * pwm_id, const struct pios_pwm_cfg * cfg)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < pios_pwm_cfg.num_channels; i++) {
|
PIOS_DEBUG_Assert(pwm_id);
|
||||||
/* Flush counter variables */
|
PIOS_DEBUG_Assert(cfg);
|
||||||
CaptureState[i] = 0;
|
|
||||||
RiseValue[i] = 0;
|
struct pios_pwm_dev * pwm_dev;
|
||||||
FallValue[i] = 0;
|
|
||||||
CaptureValue[i] = 0;
|
pwm_dev = (struct pios_pwm_dev *) PIOS_PWM_alloc();
|
||||||
|
if (!pwm_dev) goto out_fail;
|
||||||
NVIC_InitTypeDef NVIC_InitStructure = pios_pwm_cfg.irq.init;
|
|
||||||
GPIO_InitTypeDef GPIO_InitStructure = pios_pwm_cfg.gpio_init;
|
/* Bind the configuration to the device instance */
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = pios_pwm_cfg.tim_base_init;
|
pwm_dev->cfg = cfg;
|
||||||
TIM_ICInitTypeDef TIM_ICInitStructure = pios_pwm_cfg.tim_ic_init;
|
|
||||||
|
for (uint8_t i = 0; i < PIOS_PWM_NUM_INPUTS; i++) {
|
||||||
struct pios_pwm_channel channel = pios_pwm_cfg.channels[i];
|
/* Flush counter variables */
|
||||||
|
pwm_dev->CaptureState[i] = 0;
|
||||||
/* Enable appropriate clock to timer module */
|
pwm_dev->RiseValue[i] = 0;
|
||||||
switch((int32_t) channel.timer) {
|
pwm_dev->FallValue[i] = 0;
|
||||||
case (int32_t)TIM1:
|
pwm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
|
}
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
|
||||||
break;
|
uint32_t tim_id;
|
||||||
case (int32_t)TIM2:
|
if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, &tim_callbacks, (uint32_t)pwm_dev)) {
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
return -1;
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
}
|
||||||
break;
|
|
||||||
case (int32_t)TIM3:
|
/* Configure the channels to be in capture/compare mode */
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
|
for (uint8_t i = 0; i < cfg->num_channels; i++) {
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
const struct pios_tim_channel * chan = &cfg->channels[i];
|
||||||
break;
|
|
||||||
case (int32_t)TIM4:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
|
||||||
break;
|
|
||||||
#ifdef STM32F10X_HD
|
|
||||||
|
|
||||||
case (int32_t)TIM5:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM6:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM7:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM8:
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn;
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
NVIC_Init(&NVIC_InitStructure);
|
|
||||||
|
|
||||||
/* Enable GPIO */
|
|
||||||
GPIO_InitStructure.GPIO_Pin = channel.pin;
|
|
||||||
GPIO_Init(channel.port, &GPIO_InitStructure);
|
|
||||||
|
|
||||||
/* Configure timer for input capture */
|
/* Configure timer for input capture */
|
||||||
TIM_ICInitStructure.TIM_Channel = channel.channel;
|
TIM_ICInitTypeDef TIM_ICInitStructure = cfg->tim_ic_init;
|
||||||
TIM_ICInit(channel.timer, &TIM_ICInitStructure);
|
TIM_ICInitStructure.TIM_Channel = chan->timer_chan;
|
||||||
|
TIM_ICInit(chan->timer, &TIM_ICInitStructure);
|
||||||
/* Configure timer clocks */
|
|
||||||
TIM_InternalClockConfig(channel.timer);
|
|
||||||
if(channel.timer->PSC != ((PIOS_MASTER_CLOCK / 1000000) - 1))
|
|
||||||
TIM_TimeBaseInit(channel.timer, &TIM_TimeBaseStructure);
|
|
||||||
|
|
||||||
/* Enable the Capture Compare Interrupt Request */
|
/* Enable the Capture Compare Interrupt Request */
|
||||||
TIM_ITConfig(channel.timer, channel.ccr, ENABLE);
|
switch (chan->timer_chan) {
|
||||||
|
case TIM_Channel_1:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC1, ENABLE);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_2:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC2, ENABLE);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_3:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC3, ENABLE);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_4:
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_CC4, ENABLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need the update event for that timer to detect timeouts
|
||||||
|
TIM_ITConfig(chan->timer, TIM_IT_Update, ENABLE);
|
||||||
|
|
||||||
/* Enable timers */
|
|
||||||
TIM_Cmd(channel.timer, ENABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pios_pwm_cfg.remap) {
|
*pwm_id = (uint32_t) pwm_dev;
|
||||||
/* Warning, I don't think this will work for multiple remaps at once */
|
|
||||||
GPIO_PinRemapConfig(pios_pwm_cfg.remap, ENABLE);
|
return (0);
|
||||||
}
|
|
||||||
|
out_fail:
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,75 +177,101 @@ void PIOS_PWM_Init(void)
|
|||||||
*/
|
*/
|
||||||
static int32_t PIOS_PWM_Get(uint32_t rcvr_id, uint8_t channel)
|
static int32_t PIOS_PWM_Get(uint32_t rcvr_id, uint8_t channel)
|
||||||
{
|
{
|
||||||
/* Return error if channel not available */
|
struct pios_pwm_dev * pwm_dev = (struct pios_pwm_dev *)rcvr_id;
|
||||||
if (channel >= pios_pwm_cfg.num_channels) {
|
|
||||||
return -1;
|
if (!PIOS_PWM_validate(pwm_dev)) {
|
||||||
|
/* Invalid device specified */
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
}
|
}
|
||||||
return CaptureValue[channel];
|
|
||||||
|
if (channel >= PIOS_PWM_NUM_INPUTS) {
|
||||||
|
/* Channel out of range */
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
|
}
|
||||||
|
return pwm_dev->CaptureValue[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIOS_PWM_irq_handler(TIM_TypeDef * timer)
|
static void PIOS_PWM_tim_overflow_cb (uint32_t tim_id, uint32_t context, uint8_t channel, uint16_t count)
|
||||||
{
|
{
|
||||||
uint16_t val = 0;
|
struct pios_pwm_dev * pwm_dev = (struct pios_pwm_dev *)context;
|
||||||
for(uint8_t i = 0; i < pios_pwm_cfg.num_channels; i++) {
|
|
||||||
struct pios_pwm_channel channel = pios_pwm_cfg.channels[i];
|
if (!PIOS_PWM_validate(pwm_dev)) {
|
||||||
if ((channel.timer == timer) && (TIM_GetITStatus(channel.timer, channel.ccr) == SET)) {
|
/* Invalid device specified */
|
||||||
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel >= pwm_dev->cfg->num_channels) {
|
||||||
|
/* Channel out of range */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_dev->us_since_update[channel] += count;
|
||||||
|
if(pwm_dev->us_since_update[channel] >= PWM_SUPERVISOR_TIMEOUT) {
|
||||||
|
pwm_dev->CaptureState[channel] = 0;
|
||||||
|
pwm_dev->RiseValue[channel] = 0;
|
||||||
|
pwm_dev->FallValue[channel] = 0;
|
||||||
|
pwm_dev->CaptureValue[channel] = PIOS_RCVR_TIMEOUT;
|
||||||
|
pwm_dev->us_since_update[channel] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PIOS_PWM_tim_edge_cb (uint32_t tim_id, uint32_t context, uint8_t chan_idx, uint16_t count)
|
||||||
|
{
|
||||||
|
/* Recover our device context */
|
||||||
|
struct pios_pwm_dev * pwm_dev = (struct pios_pwm_dev *)context;
|
||||||
|
|
||||||
|
if (!PIOS_PWM_validate(pwm_dev)) {
|
||||||
|
/* Invalid device specified */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan_idx >= pwm_dev->cfg->num_channels) {
|
||||||
|
/* Channel out of range */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct pios_tim_channel * chan = &pwm_dev->cfg->channels[chan_idx];
|
||||||
|
|
||||||
|
if (pwm_dev->CaptureState[chan_idx] == 0) {
|
||||||
|
pwm_dev->RiseValue[chan_idx] = count;
|
||||||
|
pwm_dev->us_since_update[chan_idx] = 0;
|
||||||
|
} else {
|
||||||
|
pwm_dev->FallValue[chan_idx] = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flip state machine and capture value here
|
||||||
|
/* Simple rise or fall state machine */
|
||||||
|
TIM_ICInitTypeDef TIM_ICInitStructure = pwm_dev->cfg->tim_ic_init;
|
||||||
|
if (pwm_dev->CaptureState[chan_idx] == 0) {
|
||||||
|
/* Switch states */
|
||||||
|
pwm_dev->CaptureState[chan_idx] = 1;
|
||||||
|
|
||||||
|
/* Switch polarity of input capture */
|
||||||
|
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
|
||||||
|
TIM_ICInitStructure.TIM_Channel = chan->timer_chan;
|
||||||
|
TIM_ICInit(chan->timer, &TIM_ICInitStructure);
|
||||||
|
} else {
|
||||||
|
/* 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch states */
|
||||||
|
pwm_dev->CaptureState[chan_idx] = 0;
|
||||||
|
|
||||||
|
/* Increase supervisor counter */
|
||||||
|
pwm_dev->CapCounter[chan_idx]++;
|
||||||
|
|
||||||
|
/* Switch polarity of input capture */
|
||||||
|
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
|
||||||
|
TIM_ICInitStructure.TIM_Channel = chan->timer_chan;
|
||||||
|
TIM_ICInit(chan->timer, &TIM_ICInitStructure);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
|
|
||||||
#if defined(PIOS_INCLUDE_SBUS)
|
#if defined(PIOS_INCLUDE_SBUS)
|
||||||
|
|
||||||
/* Global Variables */
|
|
||||||
|
|
||||||
/* Provide a RCVR driver */
|
/* Provide a RCVR driver */
|
||||||
static int32_t PIOS_SBUS_Get(uint32_t rcvr_id, uint8_t channel);
|
static int32_t PIOS_SBUS_Get(uint32_t rcvr_id, uint8_t channel);
|
||||||
|
|
||||||
@ -59,27 +57,23 @@ static void PIOS_SBUS_Supervisor(uint32_t sbus_id);
|
|||||||
static void reset_channels(void)
|
static void reset_channels(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SBUS_NUMBER_OF_CHANNELS; i++) {
|
for (int i = 0; i < SBUS_NUMBER_OF_CHANNELS; i++) {
|
||||||
channel_data[i] = 0;
|
channel_data[i] = PIOS_RCVR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unroll_channels() function computes channel_data[] from received_data[]
|
* unroll_channels() function computes channel_data[] from received_data[]
|
||||||
* For efficiency it unrolls first 8 channels without loops. If other
|
* For efficiency it unrolls first 8 channels without loops and does the
|
||||||
* 8 channels are needed they can be unrolled using the same code
|
* same for other 8 channels. Also 2 discrete channels will be set.
|
||||||
* starting from s[11] instead of s[0]. Two extra digital channels are
|
|
||||||
* accessible using (s[22] & SBUS_FLAG_DGx) logical expressions.
|
|
||||||
*/
|
*/
|
||||||
static void unroll_channels(void)
|
static void unroll_channels(void)
|
||||||
{
|
{
|
||||||
uint8_t *s = received_data;
|
uint8_t *s = received_data;
|
||||||
uint16_t *d = channel_data;
|
uint16_t *d = channel_data;
|
||||||
|
|
||||||
#if (SBUS_NUMBER_OF_CHANNELS != 8)
|
|
||||||
#error Current S.Bus code unrolls only first 8 channels
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define F(v,s) ((v) >> s) & 0x7ff
|
#define F(v,s) ((v) >> s) & 0x7ff
|
||||||
|
|
||||||
|
/* unroll channels 1-8 */
|
||||||
*d++ = F(s[0] | s[1] << 8, 0);
|
*d++ = F(s[0] | s[1] << 8, 0);
|
||||||
*d++ = F(s[1] | s[2] << 8, 3);
|
*d++ = F(s[1] | s[2] << 8, 3);
|
||||||
*d++ = F(s[2] | s[3] << 8 | s[4] << 16, 6);
|
*d++ = F(s[2] | s[3] << 8 | s[4] << 16, 6);
|
||||||
@ -88,6 +82,20 @@ static void unroll_channels(void)
|
|||||||
*d++ = F(s[6] | s[7] << 8 | s[8] << 16, 7);
|
*d++ = F(s[6] | s[7] << 8 | s[8] << 16, 7);
|
||||||
*d++ = F(s[8] | s[9] << 8, 2);
|
*d++ = F(s[8] | s[9] << 8, 2);
|
||||||
*d++ = F(s[9] | s[10] << 8, 5);
|
*d++ = F(s[9] | s[10] << 8, 5);
|
||||||
|
|
||||||
|
/* unroll channels 9-16 */
|
||||||
|
*d++ = F(s[11] | s[12] << 8, 0);
|
||||||
|
*d++ = F(s[12] | s[13] << 8, 3);
|
||||||
|
*d++ = F(s[13] | s[14] << 8 | s[15] << 16, 6);
|
||||||
|
*d++ = F(s[15] | s[16] << 8, 1);
|
||||||
|
*d++ = F(s[16] | s[17] << 8, 4);
|
||||||
|
*d++ = F(s[17] | s[18] << 8 | s[19] << 16, 7);
|
||||||
|
*d++ = F(s[19] | s[20] << 8, 2);
|
||||||
|
*d++ = F(s[20] | s[21] << 8, 5);
|
||||||
|
|
||||||
|
/* unroll discrete channels 17 and 18 */
|
||||||
|
*d++ = (s[22] & SBUS_FLAG_DC1) ? SBUS_VALUE_MAX : SBUS_VALUE_MIN;
|
||||||
|
*d++ = (s[22] & SBUS_FLAG_DC2) ? SBUS_VALUE_MAX : SBUS_VALUE_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,7 +191,7 @@ static int32_t PIOS_SBUS_Get(uint32_t rcvr_id, uint8_t channel)
|
|||||||
{
|
{
|
||||||
/* return error if channel is not available */
|
/* return error if channel is not available */
|
||||||
if (channel >= SBUS_NUMBER_OF_CHANNELS) {
|
if (channel >= SBUS_NUMBER_OF_CHANNELS) {
|
||||||
return -1;
|
return PIOS_RCVR_INVALID;
|
||||||
}
|
}
|
||||||
return channel_data[channel];
|
return channel_data[channel];
|
||||||
}
|
}
|
||||||
|
@ -31,97 +31,55 @@
|
|||||||
/* Project Includes */
|
/* Project Includes */
|
||||||
#include "pios.h"
|
#include "pios.h"
|
||||||
#include "pios_servo_priv.h"
|
#include "pios_servo_priv.h"
|
||||||
|
#include "pios_tim_priv.h"
|
||||||
|
|
||||||
/* Private Function Prototypes */
|
/* Private Function Prototypes */
|
||||||
|
|
||||||
|
static const struct pios_servo_cfg * servo_cfg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise Servos
|
* Initialise Servos
|
||||||
*/
|
*/
|
||||||
void PIOS_Servo_Init(void)
|
int32_t PIOS_Servo_Init(const struct pios_servo_cfg * cfg)
|
||||||
{
|
{
|
||||||
#ifndef PIOS_ENABLE_DEBUG_PINS
|
uint32_t tim_id;
|
||||||
#if defined(PIOS_INCLUDE_SERVO)
|
if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, NULL, 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store away the requested configuration */
|
||||||
|
servo_cfg = cfg;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < pios_servo_cfg.num_channels; i++) {
|
/* Configure the channels to be in output compare mode */
|
||||||
GPIO_InitTypeDef GPIO_InitStructure = pios_servo_cfg.gpio_init;
|
for (uint8_t i = 0; i < cfg->num_channels; i++) {
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = pios_servo_cfg.tim_base_init;
|
const struct pios_tim_channel * chan = &cfg->channels[i];
|
||||||
TIM_OCInitTypeDef TIM_OCInitStructure = pios_servo_cfg.tim_oc_init;
|
|
||||||
|
|
||||||
struct pios_servo_channel channel = pios_servo_cfg.channels[i];
|
|
||||||
|
|
||||||
/* Enable appropriate clock to timer module */
|
|
||||||
switch((int32_t) channel.timer) {
|
|
||||||
case (int32_t)TIM1:
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM2:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM3:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM4:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM5:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM6:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM7:
|
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
|
|
||||||
break;
|
|
||||||
case (int32_t)TIM8:
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable GPIO */
|
|
||||||
GPIO_InitStructure.GPIO_Pin = channel.pin;
|
|
||||||
GPIO_Init(channel.port, &GPIO_InitStructure);
|
|
||||||
|
|
||||||
/* Enable time base */
|
|
||||||
TIM_TimeBaseInit(channel.timer, &TIM_TimeBaseStructure);
|
|
||||||
|
|
||||||
channel.timer->PSC = (PIOS_MASTER_CLOCK / 1000000) - 1;
|
|
||||||
|
|
||||||
/* Set up for output compare function */
|
/* Set up for output compare function */
|
||||||
switch(channel.channel) {
|
switch(chan->timer_chan) {
|
||||||
case TIM_Channel_1:
|
case TIM_Channel_1:
|
||||||
TIM_OC1Init(channel.timer, &TIM_OCInitStructure);
|
TIM_OC1Init(chan->timer, &cfg->tim_oc_init);
|
||||||
TIM_OC1PreloadConfig(channel.timer, TIM_OCPreload_Enable);
|
TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable);
|
||||||
break;
|
break;
|
||||||
case TIM_Channel_2:
|
case TIM_Channel_2:
|
||||||
TIM_OC2Init(channel.timer, &TIM_OCInitStructure);
|
TIM_OC2Init(chan->timer, &cfg->tim_oc_init);
|
||||||
TIM_OC2PreloadConfig(channel.timer, TIM_OCPreload_Enable);
|
TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable);
|
||||||
break;
|
break;
|
||||||
case TIM_Channel_3:
|
case TIM_Channel_3:
|
||||||
TIM_OC3Init(channel.timer, &TIM_OCInitStructure);
|
TIM_OC3Init(chan->timer, &cfg->tim_oc_init);
|
||||||
TIM_OC3PreloadConfig(channel.timer, TIM_OCPreload_Enable);
|
TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable);
|
||||||
break;
|
break;
|
||||||
case TIM_Channel_4:
|
case TIM_Channel_4:
|
||||||
TIM_OC4Init(channel.timer, &TIM_OCInitStructure);
|
TIM_OC4Init(chan->timer, &cfg->tim_oc_init);
|
||||||
TIM_OC4PreloadConfig(channel.timer, TIM_OCPreload_Enable);
|
TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
TIM_ARRPreloadConfig(chan->timer, ENABLE);
|
||||||
TIM_ARRPreloadConfig(channel.timer, ENABLE);
|
TIM_CtrlPWMOutputs(chan->timer, ENABLE);
|
||||||
TIM_CtrlPWMOutputs(channel.timer, ENABLE);
|
TIM_Cmd(chan->timer, ENABLE);
|
||||||
TIM_Cmd(channel.timer, ENABLE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pios_servo_cfg.remap) {
|
return 0;
|
||||||
/* Warning, I don't think this will work for multiple remaps at once */
|
|
||||||
GPIO_PinRemapConfig(pios_servo_cfg.remap, ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIOS_INCLUDE_SERVO
|
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,31 +89,31 @@ void PIOS_Servo_Init(void)
|
|||||||
*/
|
*/
|
||||||
void PIOS_Servo_SetHz(uint16_t * speeds, uint8_t banks)
|
void PIOS_Servo_SetHz(uint16_t * speeds, uint8_t banks)
|
||||||
{
|
{
|
||||||
#ifndef PIOS_ENABLE_DEBUG_PINS
|
if (!servo_cfg) {
|
||||||
#if defined(PIOS_INCLUDE_SERVO)
|
return;
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = pios_servo_cfg.tim_base_init;
|
}
|
||||||
|
|
||||||
|
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init;
|
||||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1;
|
TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1;
|
||||||
|
|
||||||
uint8_t set = 0;
|
uint8_t set = 0;
|
||||||
|
|
||||||
for(uint8_t i = 0; (i < pios_servo_cfg.num_channels) && (set < banks); i++) {
|
for(uint8_t i = 0; (i < servo_cfg->num_channels) && (set < banks); i++) {
|
||||||
bool new = true;
|
bool new = true;
|
||||||
struct pios_servo_channel channel = pios_servo_cfg.channels[i];
|
const struct pios_tim_channel * chan = &servo_cfg->channels[i];
|
||||||
|
|
||||||
/* See if any previous channels use that same timer */
|
/* See if any previous channels use that same timer */
|
||||||
for(uint8_t j = 0; (j < i) && new; j++)
|
for(uint8_t j = 0; (j < i) && new; j++)
|
||||||
new &= channel.timer != pios_servo_cfg.channels[j].timer;
|
new &= chan->timer != servo_cfg->channels[j].timer;
|
||||||
|
|
||||||
if(new) {
|
if(new) {
|
||||||
TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1);
|
TIM_TimeBaseStructure.TIM_Period = ((1000000 / speeds[set]) - 1);
|
||||||
TIM_TimeBaseInit(channel.timer, &TIM_TimeBaseStructure);
|
TIM_TimeBaseInit(chan->timer, &TIM_TimeBaseStructure);
|
||||||
set++;
|
set++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // PIOS_INCLUDE_SERVO
|
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,29 +121,27 @@ void PIOS_Servo_SetHz(uint16_t * speeds, uint8_t banks)
|
|||||||
* \param[in] Servo Servo number (0-7)
|
* \param[in] Servo Servo number (0-7)
|
||||||
* \param[in] Position Servo position in microseconds
|
* \param[in] Position Servo position in microseconds
|
||||||
*/
|
*/
|
||||||
void PIOS_Servo_Set(uint8_t Servo, uint16_t Position)
|
void PIOS_Servo_Set(uint8_t servo, uint16_t position)
|
||||||
{
|
{
|
||||||
#ifndef PIOS_ENABLE_DEBUG_PINS
|
|
||||||
#if defined(PIOS_INCLUDE_SERVO)
|
|
||||||
/* Make sure servo exists */
|
/* Make sure servo exists */
|
||||||
if (Servo < pios_servo_cfg.num_channels && Servo >= 0) {
|
if (!servo_cfg || servo >= servo_cfg->num_channels) {
|
||||||
/* Update the position */
|
return;
|
||||||
|
}
|
||||||
switch(pios_servo_cfg.channels[Servo].channel) {
|
|
||||||
case TIM_Channel_1:
|
/* Update the position */
|
||||||
TIM_SetCompare1(pios_servo_cfg.channels[Servo].timer, Position);
|
const struct pios_tim_channel * chan = &servo_cfg->channels[servo];
|
||||||
break;
|
switch(chan->timer_chan) {
|
||||||
case TIM_Channel_2:
|
case TIM_Channel_1:
|
||||||
TIM_SetCompare2(pios_servo_cfg.channels[Servo].timer, Position);
|
TIM_SetCompare1(chan->timer, position);
|
||||||
break;
|
break;
|
||||||
case TIM_Channel_3:
|
case TIM_Channel_2:
|
||||||
TIM_SetCompare3(pios_servo_cfg.channels[Servo].timer, Position);
|
TIM_SetCompare2(chan->timer, position);
|
||||||
break;
|
break;
|
||||||
case TIM_Channel_4:
|
case TIM_Channel_3:
|
||||||
TIM_SetCompare4(pios_servo_cfg.channels[Servo].timer, Position);
|
TIM_SetCompare3(chan->timer, position);
|
||||||
break;
|
break;
|
||||||
}
|
case TIM_Channel_4:
|
||||||
|
TIM_SetCompare4(chan->timer, position);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif // PIOS_INCLUDE_SERVO
|
|
||||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,11 @@
|
|||||||
|
|
||||||
/* Project Includes */
|
/* Project Includes */
|
||||||
#include "pios.h"
|
#include "pios.h"
|
||||||
#include "pios_spektrum_priv.h"
|
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
#if defined(PIOS_INCLUDE_SPEKTRUM)
|
||||||
|
|
||||||
|
#include "pios_spektrum_priv.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Note Framesyncing:
|
* @Note Framesyncing:
|
||||||
* The code resets the watchdog timer whenever a single byte is received, so what watchdog code
|
* The code resets the watchdog timer whenever a single byte is received, so what watchdog code
|
||||||
@ -51,22 +52,80 @@ const struct pios_rcvr_driver pios_spektrum_rcvr_driver = {
|
|||||||
.read = PIOS_SPEKTRUM_Get,
|
.read = PIOS_SPEKTRUM_Get,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Local Variables */
|
enum pios_spektrum_dev_magic {
|
||||||
static uint16_t CaptureValue[PIOS_SPEKTRUM_NUM_INPUTS],CaptureValueTemp[PIOS_SPEKTRUM_NUM_INPUTS];
|
PIOS_SPEKTRUM_DEV_MAGIC = 0xa9b9c9d9,
|
||||||
static uint8_t prev_byte = 0xFF, sync = 0, bytecount = 0, datalength=0, frame_error=0, byte_array[20] = { 0 };
|
};
|
||||||
uint8_t sync_of = 0;
|
|
||||||
uint16_t supv_timer=0;
|
struct pios_spektrum_fsm {
|
||||||
|
uint16_t channel;
|
||||||
|
uint16_t CaptureValue[PIOS_SPEKTRUM_NUM_INPUTS];
|
||||||
|
uint16_t CaptureValueTemp[PIOS_SPEKTRUM_NUM_INPUTS];
|
||||||
|
uint8_t prev_byte;
|
||||||
|
uint8_t sync;
|
||||||
|
uint8_t bytecount;
|
||||||
|
uint8_t datalength;
|
||||||
|
uint8_t frame_error;
|
||||||
|
uint8_t sync_of;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_spektrum_dev {
|
||||||
|
enum pios_spektrum_dev_magic magic;
|
||||||
|
const struct pios_spektrum_cfg * cfg;
|
||||||
|
|
||||||
|
struct pios_spektrum_fsm fsm;
|
||||||
|
|
||||||
|
uint16_t supv_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool PIOS_SPEKTRUM_validate(struct pios_spektrum_dev * spektrum_dev)
|
||||||
|
{
|
||||||
|
return (spektrum_dev->magic == PIOS_SPEKTRUM_DEV_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
|
static struct pios_spektrum_dev * PIOS_SPEKTRUM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_spektrum_dev * spektrum_dev;
|
||||||
|
|
||||||
|
spektrum_dev = (struct pios_spektrum_dev *)pvPortMalloc(sizeof(*spektrum_dev));
|
||||||
|
if (!spektrum_dev) return(NULL);
|
||||||
|
|
||||||
|
spektrum_dev->magic = PIOS_SPEKTRUM_DEV_MAGIC;
|
||||||
|
return(spektrum_dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct pios_spektrum_dev pios_spektrum_devs[PIOS_SPEKTRUM_MAX_DEVS];
|
||||||
|
static uint8_t pios_spektrum_num_devs;
|
||||||
|
static struct pios_spektrum_dev * PIOS_SPEKTRUM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_spektrum_dev * spektrum_dev;
|
||||||
|
|
||||||
|
if (pios_spektrum_num_devs >= PIOS_SPEKTRUM_MAX_DEVS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
spektrum_dev = &pios_spektrum_devs[pios_spektrum_num_devs++];
|
||||||
|
spektrum_dev->magic = PIOS_SPEKTRUM_DEV_MAGIC;
|
||||||
|
|
||||||
|
return (spektrum_dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id);
|
static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id);
|
||||||
static bool PIOS_SPEKTRUM_Bind(const struct pios_spektrum_cfg * cfg, uint8_t bind);
|
static bool PIOS_SPEKTRUM_Bind(const struct pios_spektrum_cfg * cfg, uint8_t bind);
|
||||||
static int32_t PIOS_SPEKTRUM_Decode(uint8_t b);
|
static int32_t PIOS_SPEKTRUM_UpdateFSM(struct pios_spektrum_fsm * fsm, uint8_t b);
|
||||||
|
|
||||||
static uint16_t PIOS_SPEKTRUM_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
|
static uint16_t PIOS_SPEKTRUM_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
|
||||||
{
|
{
|
||||||
|
struct pios_spektrum_dev * spektrum_dev = (struct pios_spektrum_dev *)context;
|
||||||
|
|
||||||
|
bool valid = PIOS_SPEKTRUM_validate(spektrum_dev);
|
||||||
|
PIOS_Assert(valid);
|
||||||
|
|
||||||
/* process byte(s) and clear receive timer */
|
/* process byte(s) and clear receive timer */
|
||||||
for (uint8_t i = 0; i < buf_len; i++) {
|
for (uint8_t i = 0; i < buf_len; i++) {
|
||||||
PIOS_SPEKTRUM_Decode(buf[i]);
|
PIOS_SPEKTRUM_UpdateFSM(&(spektrum_dev->fsm), buf[i]);
|
||||||
supv_timer = 0;
|
spektrum_dev->supv_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always signal that we can accept another byte */
|
/* Always signal that we can accept another byte */
|
||||||
@ -81,23 +140,114 @@ static uint16_t PIOS_SPEKTRUM_RxInCallback(uint32_t context, uint8_t * buf, uint
|
|||||||
return (buf_len);
|
return (buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PIOS_SPEKTRUM_ResetFSM(struct pios_spektrum_fsm * fsm)
|
||||||
|
{
|
||||||
|
fsm->channel = 0;
|
||||||
|
fsm->prev_byte = 0xFF;
|
||||||
|
fsm->sync = 0;
|
||||||
|
fsm->bytecount = 0;
|
||||||
|
fsm->datalength = 0;
|
||||||
|
fsm->frame_error = 0;
|
||||||
|
fsm->sync_of = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a byte
|
||||||
|
* \param[in] b byte which should be spektrum decoded
|
||||||
|
* \return 0 if no error
|
||||||
|
* \return -1 if USART not available
|
||||||
|
* \return -2 if buffer full (retry)
|
||||||
|
*/
|
||||||
|
static int32_t PIOS_SPEKTRUM_UpdateFSM(struct pios_spektrum_fsm * fsm, uint8_t b)
|
||||||
|
{
|
||||||
|
fsm->bytecount++;
|
||||||
|
if (fsm->sync == 0) {
|
||||||
|
/* Known sync bytes, 0x01, 0x02, 0x12, 0xb2 */
|
||||||
|
/* 0xb2 DX8 3bind pulses only */
|
||||||
|
if (fsm->bytecount == 2) {
|
||||||
|
if ((b == 0x01) || (b == 0x02) || (b == 0xb2)) {
|
||||||
|
fsm->datalength=0; // 10bit
|
||||||
|
fsm->sync = 1;
|
||||||
|
fsm->bytecount = 2;
|
||||||
|
}
|
||||||
|
else if(b == 0x12) {
|
||||||
|
fsm->datalength=1; // 11bit
|
||||||
|
fsm->sync = 1;
|
||||||
|
fsm->bytecount = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fsm->bytecount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((fsm->bytecount % 2) == 0) {
|
||||||
|
uint16_t data;
|
||||||
|
uint8_t channeln;
|
||||||
|
|
||||||
|
fsm->channel = (fsm->prev_byte << 8) + b;
|
||||||
|
channeln = (fsm->channel >> (10+fsm->datalength)) & 0x0F;
|
||||||
|
data = fsm->channel & (0x03FF+(0x0400*fsm->datalength));
|
||||||
|
if(channeln==0 && data<10) // discard frame if throttle misbehaves
|
||||||
|
{
|
||||||
|
fsm->frame_error=1;
|
||||||
|
}
|
||||||
|
if (channeln < PIOS_SPEKTRUM_NUM_INPUTS && !fsm->frame_error)
|
||||||
|
fsm->CaptureValueTemp[channeln] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fsm->bytecount == 16) {
|
||||||
|
fsm->bytecount = 0;
|
||||||
|
fsm->sync = 0;
|
||||||
|
fsm->sync_of = 0;
|
||||||
|
if (!fsm->frame_error)
|
||||||
|
{
|
||||||
|
for(int i=0;i<PIOS_SPEKTRUM_NUM_INPUTS;i++)
|
||||||
|
{
|
||||||
|
fsm->CaptureValue[i] = fsm->CaptureValueTemp[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fsm->frame_error=0;
|
||||||
|
}
|
||||||
|
fsm->prev_byte = b;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind and Initialise Spektrum satellite receiver
|
* Bind and Initialise Spektrum satellite receiver
|
||||||
*/
|
*/
|
||||||
int32_t PIOS_SPEKTRUM_Init(uint32_t * spektrum_id, const struct pios_spektrum_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t bind)
|
int32_t PIOS_SPEKTRUM_Init(uint32_t * spektrum_id, const struct pios_spektrum_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t bind)
|
||||||
{
|
{
|
||||||
// TODO: need setting flag for bind on next powerup
|
PIOS_DEBUG_Assert(spektrum_id);
|
||||||
|
PIOS_DEBUG_Assert(cfg);
|
||||||
|
PIOS_DEBUG_Assert(driver);
|
||||||
|
|
||||||
|
struct pios_spektrum_dev * spektrum_dev;
|
||||||
|
|
||||||
|
spektrum_dev = (struct pios_spektrum_dev *) PIOS_SPEKTRUM_alloc();
|
||||||
|
if (!spektrum_dev) goto out_fail;
|
||||||
|
|
||||||
|
/* Bind the configuration to the device instance */
|
||||||
|
spektrum_dev->cfg = cfg;
|
||||||
|
|
||||||
if (bind) {
|
if (bind) {
|
||||||
PIOS_SPEKTRUM_Bind(cfg,bind);
|
PIOS_SPEKTRUM_Bind(cfg,bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
(driver->bind_rx_cb)(lower_id, PIOS_SPEKTRUM_RxInCallback, 0);
|
PIOS_SPEKTRUM_ResetFSM(&(spektrum_dev->fsm));
|
||||||
|
|
||||||
if (!PIOS_RTC_RegisterTickCallback(PIOS_SPEKTRUM_Supervisor, 0)) {
|
*spektrum_id = (uint32_t)spektrum_dev;
|
||||||
|
|
||||||
|
(driver->bind_rx_cb)(lower_id, PIOS_SPEKTRUM_RxInCallback, *spektrum_id);
|
||||||
|
|
||||||
|
if (!PIOS_RTC_RegisterTickCallback(PIOS_SPEKTRUM_Supervisor, *spektrum_id)) {
|
||||||
PIOS_DEBUG_Assert(0);
|
PIOS_DEBUG_Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
out_fail:
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,11 +258,16 @@ int32_t PIOS_SPEKTRUM_Init(uint32_t * spektrum_id, const struct pios_spektrum_cf
|
|||||||
*/
|
*/
|
||||||
static int32_t PIOS_SPEKTRUM_Get(uint32_t rcvr_id, uint8_t channel)
|
static int32_t PIOS_SPEKTRUM_Get(uint32_t rcvr_id, uint8_t channel)
|
||||||
{
|
{
|
||||||
|
struct pios_spektrum_dev * spektrum_dev = (struct pios_spektrum_dev *)rcvr_id;
|
||||||
|
|
||||||
|
if(!PIOS_SPEKTRUM_validate(spektrum_dev))
|
||||||
|
return PIOS_RCVR_INVALID;
|
||||||
|
|
||||||
/* Return error if channel not available */
|
/* Return error if channel not available */
|
||||||
if (channel >= PIOS_SPEKTRUM_NUM_INPUTS) {
|
if (channel >= PIOS_SPEKTRUM_NUM_INPUTS) {
|
||||||
return -1;
|
return PIOS_RCVR_INVALID;
|
||||||
}
|
}
|
||||||
return CaptureValue[channel];
|
return spektrum_dev->fsm.CaptureValue[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,115 +306,39 @@ static bool PIOS_SPEKTRUM_Bind(const struct pios_spektrum_cfg * cfg, uint8_t bin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes a byte
|
|
||||||
* \param[in] b byte which should be spektrum decoded
|
|
||||||
* \return 0 if no error
|
|
||||||
* \return -1 if USART not available
|
|
||||||
* \return -2 if buffer full (retry)
|
|
||||||
* \note Applications shouldn't call these functions directly
|
|
||||||
*/
|
|
||||||
static int32_t PIOS_SPEKTRUM_Decode(uint8_t b)
|
|
||||||
{
|
|
||||||
static uint16_t channel = 0; /*, sync_word = 0;*/
|
|
||||||
uint8_t channeln = 0, frame = 0;
|
|
||||||
uint16_t data = 0;
|
|
||||||
byte_array[bytecount] = b;
|
|
||||||
bytecount++;
|
|
||||||
if (sync == 0) {
|
|
||||||
//sync_word = (prev_byte << 8) + b;
|
|
||||||
#if 0
|
|
||||||
/* maybe create object to show this data */
|
|
||||||
if(bytecount==1)
|
|
||||||
{
|
|
||||||
/* record losscounter into channel8 */
|
|
||||||
CaptureValueTemp[7]=b;
|
|
||||||
/* instant write */
|
|
||||||
CaptureValue[7]=b;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Known sync bytes, 0x01, 0x02, 0x12, 0xb2 */
|
|
||||||
/* 0xb2 DX8 3bind pulses only */
|
|
||||||
if (bytecount == 2) {
|
|
||||||
if ((b == 0x01) || (b == 0xb2)) {
|
|
||||||
datalength=0; // 10bit
|
|
||||||
//frames=1;
|
|
||||||
sync = 1;
|
|
||||||
bytecount = 2;
|
|
||||||
}
|
|
||||||
else if(b == 0x02) {
|
|
||||||
datalength=0; // 10bit
|
|
||||||
//frames=2;
|
|
||||||
sync = 1;
|
|
||||||
bytecount = 2;
|
|
||||||
}
|
|
||||||
else if(b == 0x12) {
|
|
||||||
datalength=1; // 11bit
|
|
||||||
//frames=2;
|
|
||||||
sync = 1;
|
|
||||||
bytecount = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bytecount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((bytecount % 2) == 0) {
|
|
||||||
channel = (prev_byte << 8) + b;
|
|
||||||
frame = channel >> 15;
|
|
||||||
channeln = (channel >> (10+datalength)) & 0x0F;
|
|
||||||
data = channel & (0x03FF+(0x0400*datalength));
|
|
||||||
if(channeln==0 && data<10) // discard frame if throttle misbehaves
|
|
||||||
{
|
|
||||||
frame_error=1;
|
|
||||||
}
|
|
||||||
if (channeln < PIOS_SPEKTRUM_NUM_INPUTS && !frame_error)
|
|
||||||
CaptureValueTemp[channeln] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bytecount == 16) {
|
|
||||||
//PIOS_COM_SendBufferNonBlocking(PIOS_COM_TELEM_RF,byte_array,16); //00 2c 58 84 b0 dc ff
|
|
||||||
bytecount = 0;
|
|
||||||
sync = 0;
|
|
||||||
sync_of = 0;
|
|
||||||
if (!frame_error)
|
|
||||||
{
|
|
||||||
for(int i=0;i<PIOS_SPEKTRUM_NUM_INPUTS;i++)
|
|
||||||
{
|
|
||||||
CaptureValue[i] = CaptureValueTemp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frame_error=0;
|
|
||||||
}
|
|
||||||
prev_byte = b;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@brief This function is called between frames and when a spektrum word hasnt been decoded for too long
|
*@brief This function is called between frames and when a spektrum word hasnt been decoded for too long
|
||||||
*@brief clears the channel values
|
*@brief clears the channel values
|
||||||
*/
|
*/
|
||||||
static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id) {
|
static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id)
|
||||||
|
{
|
||||||
|
struct pios_spektrum_dev * spektrum_dev = (struct pios_spektrum_dev *)spektrum_id;
|
||||||
|
|
||||||
|
bool valid = PIOS_SPEKTRUM_validate(spektrum_dev);
|
||||||
|
PIOS_Assert(valid);
|
||||||
|
|
||||||
/* 625hz */
|
/* 625hz */
|
||||||
supv_timer++;
|
spektrum_dev->supv_timer++;
|
||||||
if(supv_timer > 4) {
|
if(spektrum_dev->supv_timer > 4) {
|
||||||
/* sync between frames */
|
/* sync between frames */
|
||||||
sync = 0;
|
struct pios_spektrum_fsm * fsm = &(spektrum_dev->fsm);
|
||||||
bytecount = 0;
|
|
||||||
prev_byte = 0xFF;
|
fsm->sync = 0;
|
||||||
frame_error = 0;
|
fsm->bytecount = 0;
|
||||||
sync_of++;
|
fsm->prev_byte = 0xFF;
|
||||||
|
fsm->frame_error = 0;
|
||||||
|
fsm->sync_of++;
|
||||||
/* watchdog activated after 200ms silence */
|
/* watchdog activated after 200ms silence */
|
||||||
if (sync_of > 30) {
|
if (fsm->sync_of > 30) {
|
||||||
|
|
||||||
/* signal lost */
|
/* signal lost */
|
||||||
sync_of = 0;
|
fsm->sync_of = 0;
|
||||||
for (int i = 0; i < PIOS_SPEKTRUM_NUM_INPUTS; i++) {
|
for (int i = 0; i < PIOS_SPEKTRUM_NUM_INPUTS; i++) {
|
||||||
CaptureValue[i] = 0;
|
fsm->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||||
CaptureValueTemp[i] = 0;
|
fsm->CaptureValueTemp[i] = PIOS_RCVR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
supv_timer = 0;
|
spektrum_dev->supv_timer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +46,10 @@ static bool PIOS_SPI_validate(struct pios_spi_dev * com_dev)
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_spi_dev * PIOS_SPI_alloc(void)
|
static struct pios_spi_dev * PIOS_SPI_alloc(void)
|
||||||
{
|
{
|
||||||
return (malloc(sizeof(struct pios_spi_dev)));
|
return (pvPortMalloc(sizeof(struct pios_spi_dev)));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static struct pios_spi_dev pios_spi_devs[PIOS_SPI_MAX_DEVS];
|
static struct pios_spi_dev pios_spi_devs[PIOS_SPI_MAX_DEVS];
|
||||||
|
427
flight/PiOS/STM32F10x/pios_tim.c
Normal file
427
flight/PiOS/STM32F10x/pios_tim.c
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
#include "pios.h"
|
||||||
|
|
||||||
|
#include "pios_tim.h"
|
||||||
|
#include "pios_tim_priv.h"
|
||||||
|
|
||||||
|
enum pios_tim_dev_magic {
|
||||||
|
PIOS_TIM_DEV_MAGIC = 0x87654098,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_tim_dev {
|
||||||
|
enum pios_tim_dev_magic magic;
|
||||||
|
|
||||||
|
const struct pios_tim_channel * channels;
|
||||||
|
uint8_t num_channels;
|
||||||
|
|
||||||
|
const struct pios_tim_callbacks * callbacks;
|
||||||
|
uint32_t context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static bool PIOS_TIM_validate(struct pios_tim_dev * tim_dev)
|
||||||
|
{
|
||||||
|
return (tim_dev->magic == PIOS_TIM_DEV_MAGIC);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
||||||
|
static struct pios_tim_dev * PIOS_TIM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_tim_dev * tim_dev;
|
||||||
|
|
||||||
|
tim_dev = (struct pios_tim_dev *)malloc(sizeof(*tim_dev));
|
||||||
|
if (!tim_dev) return(NULL);
|
||||||
|
|
||||||
|
tim_dev->magic = PIOS_TIM_DEV_MAGIC;
|
||||||
|
return(tim_dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct pios_tim_dev pios_tim_devs[PIOS_TIM_MAX_DEVS];
|
||||||
|
static uint8_t pios_tim_num_devs;
|
||||||
|
static struct pios_tim_dev * PIOS_TIM_alloc(void)
|
||||||
|
{
|
||||||
|
struct pios_tim_dev * tim_dev;
|
||||||
|
|
||||||
|
if (pios_tim_num_devs >= PIOS_TIM_MAX_DEVS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
tim_dev = &pios_tim_devs[pios_tim_num_devs++];
|
||||||
|
tim_dev->magic = PIOS_TIM_DEV_MAGIC;
|
||||||
|
|
||||||
|
return (tim_dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg * cfg)
|
||||||
|
{
|
||||||
|
PIOS_DEBUG_Assert(cfg);
|
||||||
|
|
||||||
|
/* Enable appropriate clock to timer module */
|
||||||
|
switch((uint32_t) cfg->timer) {
|
||||||
|
case (uint32_t)TIM1:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM2:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM3:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM4:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
||||||
|
break;
|
||||||
|
#ifdef STM32F10X_HD
|
||||||
|
case (uint32_t)TIM5:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM6:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM7:
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t)TIM8:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the dividers for this timer */
|
||||||
|
TIM_TimeBaseInit(cfg->timer, cfg->time_base_init);
|
||||||
|
|
||||||
|
/* Configure internal timer clocks */
|
||||||
|
TIM_InternalClockConfig(cfg->timer);
|
||||||
|
|
||||||
|
/* Enable timers */
|
||||||
|
TIM_Cmd(cfg->timer, ENABLE);
|
||||||
|
|
||||||
|
/* Enable Interrupts */
|
||||||
|
NVIC_Init(&cfg->irq.init);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t PIOS_TIM_InitChannels(uint32_t * tim_id, const struct pios_tim_channel * channels, uint8_t num_channels, const struct pios_tim_callbacks * callbacks, uint32_t context)
|
||||||
|
{
|
||||||
|
PIOS_Assert(channels);
|
||||||
|
PIOS_Assert(num_channels);
|
||||||
|
|
||||||
|
struct pios_tim_dev * tim_dev;
|
||||||
|
tim_dev = (struct pios_tim_dev *) PIOS_TIM_alloc();
|
||||||
|
if (!tim_dev) goto out_fail;
|
||||||
|
|
||||||
|
/* Bind the configuration to the device instance */
|
||||||
|
tim_dev->channels = channels;
|
||||||
|
tim_dev->num_channels = num_channels;
|
||||||
|
tim_dev->callbacks = callbacks;
|
||||||
|
tim_dev->context = context;
|
||||||
|
|
||||||
|
/* Configure the pins */
|
||||||
|
for (uint8_t i = 0; i < num_channels; i++) {
|
||||||
|
const struct pios_tim_channel * chan = &(channels[i]);
|
||||||
|
|
||||||
|
/* Enable the peripheral clock for the GPIO */
|
||||||
|
switch ((uint32_t)chan->pin.gpio) {
|
||||||
|
case (uint32_t) GPIOA:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t) GPIOB:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
||||||
|
break;
|
||||||
|
case (uint32_t) GPIOC:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PIOS_Assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GPIO_Init(chan->pin.gpio, &chan->pin.init);
|
||||||
|
|
||||||
|
if (chan->remap) {
|
||||||
|
GPIO_PinRemapConfig(chan->remap, ENABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*tim_id = (uint32_t)tim_dev;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
out_fail:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PIOS_TIM_generic_irq_handler(TIM_TypeDef * timer)
|
||||||
|
{
|
||||||
|
/* 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];
|
||||||
|
|
||||||
|
if (!tim_dev->channels || tim_dev->num_channels == 0) {
|
||||||
|
/* No channels to process on this client */
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (chan->timer != timer) {
|
||||||
|
/* channel is not on this timer */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure out which interrupt bit we should be looking at */
|
||||||
|
uint16_t timer_it;
|
||||||
|
switch (chan->timer_chan) {
|
||||||
|
case TIM_Channel_1:
|
||||||
|
timer_it = TIM_IT_CC1;
|
||||||
|
break;
|
||||||
|
case TIM_Channel_2:
|
||||||
|
timer_it = TIM_IT_CC2;
|
||||||
|
break;
|
||||||
|
case TIM_Channel_3:
|
||||||
|
timer_it = TIM_IT_CC3;
|
||||||
|
break;
|
||||||
|
case TIM_Channel_4:
|
||||||
|
timer_it = TIM_IT_CC4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PIOS_Assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool edge_event;
|
||||||
|
uint16_t edge_count;
|
||||||
|
if (TIM_GetITStatus(chan->timer, timer_it) == SET) {
|
||||||
|
TIM_ClearITPendingBit(chan->timer, timer_it);
|
||||||
|
|
||||||
|
/* Read the current counter */
|
||||||
|
switch(chan->timer_chan) {
|
||||||
|
case TIM_Channel_1:
|
||||||
|
edge_count = TIM_GetCapture1(chan->timer);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_2:
|
||||||
|
edge_count = TIM_GetCapture2(chan->timer);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_3:
|
||||||
|
edge_count = TIM_GetCapture3(chan->timer);
|
||||||
|
break;
|
||||||
|
case TIM_Channel_4:
|
||||||
|
edge_count = TIM_GetCapture4(chan->timer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PIOS_Assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
edge_event = true;
|
||||||
|
} else {
|
||||||
|
edge_event = false;
|
||||||
|
edge_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tim_dev->callbacks) {
|
||||||
|
/* No callbacks registered, we're done with this channel */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate the appropriate callbacks */
|
||||||
|
if (overflow_event & edge_event) {
|
||||||
|
/*
|
||||||
|
* When both edge and overflow happen in the same interrupt, we
|
||||||
|
* need a heuristic to determine the order of the edge and overflow
|
||||||
|
* events so that the callbacks happen in the right order. If we
|
||||||
|
* 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
|
||||||
|
* edge happened just after the overflow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (edge_count < 16) {
|
||||||
|
/* Call the overflow callback first */
|
||||||
|
if (tim_dev->callbacks->overflow) {
|
||||||
|
(*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
overflow_count);
|
||||||
|
}
|
||||||
|
/* Call the edge callback second */
|
||||||
|
if (tim_dev->callbacks->edge) {
|
||||||
|
(*tim_dev->callbacks->edge)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
edge_count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Call the edge callback first */
|
||||||
|
if (tim_dev->callbacks->edge) {
|
||||||
|
(*tim_dev->callbacks->edge)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
edge_count);
|
||||||
|
}
|
||||||
|
/* Call the overflow callback second */
|
||||||
|
if (tim_dev->callbacks->overflow) {
|
||||||
|
(*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
overflow_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (overflow_event && tim_dev->callbacks->overflow) {
|
||||||
|
(*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
overflow_count);
|
||||||
|
} else if (edge_event && tim_dev->callbacks->edge) {
|
||||||
|
(*tim_dev->callbacks->edge)((uint32_t)tim_dev,
|
||||||
|
tim_dev->context,
|
||||||
|
j,
|
||||||
|
edge_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* Bind Interrupt Handlers
|
||||||
|
*
|
||||||
|
* Map all valid TIM IRQs to the common interrupt handler
|
||||||
|
* and give it enough context to properly demux the various timers
|
||||||
|
*/
|
||||||
|
void TIM1_UP_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_UP_irq_handler")));
|
||||||
|
static void PIOS_TIM_1_UP_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM1_CC_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_CC_irq_handler")));
|
||||||
|
static void PIOS_TIM_1_CC_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM2_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_2_irq_handler")));
|
||||||
|
static void PIOS_TIM_2_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM3_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_3_irq_handler")));
|
||||||
|
static void PIOS_TIM_3_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM4_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_4_irq_handler")));
|
||||||
|
static void PIOS_TIM_4_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM5_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_5_irq_handler")));
|
||||||
|
static void PIOS_TIM_5_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM6_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_6_irq_handler")));
|
||||||
|
static void PIOS_TIM_6_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM7_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_7_irq_handler")));
|
||||||
|
static void PIOS_TIM_7_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM8_UP_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_UP_irq_handler")));
|
||||||
|
static void PIOS_TIM_8_UP_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIM8_CC_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_CC_irq_handler")));
|
||||||
|
static void PIOS_TIM_8_CC_irq_handler (void)
|
||||||
|
{
|
||||||
|
PIOS_TIM_generic_irq_handler (TIM8);
|
||||||
|
}
|
||||||
|
|
@ -70,12 +70,12 @@ static bool PIOS_USART_validate(struct pios_usart_dev * usart_dev)
|
|||||||
return (usart_dev->magic == PIOS_USART_DEV_MAGIC);
|
return (usart_dev->magic == PIOS_USART_DEV_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_usart_dev * PIOS_USART_alloc(void)
|
static struct pios_usart_dev * PIOS_USART_alloc(void)
|
||||||
{
|
{
|
||||||
struct pios_usart_dev * usart_dev;
|
struct pios_usart_dev * usart_dev;
|
||||||
|
|
||||||
usart_dev = (struct pios_usart_dev *)malloc(sizeof(*usart_dev));
|
usart_dev = (struct pios_usart_dev *)pvPortMalloc(sizeof(*usart_dev));
|
||||||
if (!usart_dev) return(NULL);
|
if (!usart_dev) return(NULL);
|
||||||
|
|
||||||
usart_dev->magic = PIOS_USART_DEV_MAGIC;
|
usart_dev->magic = PIOS_USART_DEV_MAGIC;
|
||||||
|
@ -75,12 +75,12 @@ static bool PIOS_USB_HID_validate(struct pios_usb_hid_dev * usb_hid_dev)
|
|||||||
return (usb_hid_dev->magic == PIOS_USB_HID_DEV_MAGIC);
|
return (usb_hid_dev->magic == PIOS_USB_HID_DEV_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_usb_hid_dev * PIOS_USB_HID_alloc(void)
|
static struct pios_usb_hid_dev * PIOS_USB_HID_alloc(void)
|
||||||
{
|
{
|
||||||
struct pios_usb_hid_dev * usb_hid_dev;
|
struct pios_usb_hid_dev * usb_hid_dev;
|
||||||
|
|
||||||
usb_hid_dev = (struct pios_usb_hid_dev *)malloc(sizeof(*usb_hid_dev));
|
usb_hid_dev = (struct pios_usb_hid_dev *)pvPortMalloc(sizeof(*usb_hid_dev));
|
||||||
if (!usb_hid_dev) return(NULL);
|
if (!usb_hid_dev) return(NULL);
|
||||||
|
|
||||||
usb_hid_dev->magic = PIOS_USB_HID_DEV_MAGIC;
|
usb_hid_dev->magic = PIOS_USB_HID_DEV_MAGIC;
|
||||||
|
@ -33,7 +33,9 @@
|
|||||||
|
|
||||||
extern const char *PIOS_DEBUG_AssertMsg;
|
extern const char *PIOS_DEBUG_AssertMsg;
|
||||||
|
|
||||||
void PIOS_DEBUG_Init(void);
|
#include <pios_tim_priv.h>
|
||||||
|
|
||||||
|
void PIOS_DEBUG_Init(const struct pios_tim_channel * channels, uint8_t num_channels);
|
||||||
void PIOS_DEBUG_PinHigh(uint8_t pin);
|
void PIOS_DEBUG_PinHigh(uint8_t pin);
|
||||||
void PIOS_DEBUG_PinLow(uint8_t pin);
|
void PIOS_DEBUG_PinLow(uint8_t pin);
|
||||||
void PIOS_DEBUG_PinValue8Bit(uint8_t value);
|
void PIOS_DEBUG_PinValue8Bit(uint8_t value);
|
||||||
|
47
flight/PiOS/inc/pios_gcsrcvr_priv.h
Normal file
47
flight/PiOS/inc/pios_gcsrcvr_priv.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||||
|
* @{
|
||||||
|
* @addtogroup PIOS_GCSRCVR GCS Receiver Functions
|
||||||
|
* @brief PIOS interface to read from GCS receiver port
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file pios_gcsrcvr_priv.h
|
||||||
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @brief GCS receiver private functions
|
||||||
|
* @see The GNU Public License (GPL) Version 3
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PIOS_GCSRCVR_PRIV_H
|
||||||
|
#define PIOS_GCSRCVR_PRIV_H
|
||||||
|
|
||||||
|
#include <pios.h>
|
||||||
|
|
||||||
|
#include "gcsreceiver.h"
|
||||||
|
|
||||||
|
extern const struct pios_rcvr_driver pios_gcsrcvr_rcvr_driver;
|
||||||
|
|
||||||
|
extern void PIOS_GCSRCVR_Init(void);
|
||||||
|
|
||||||
|
#endif /* PIOS_GCSRCVR_PRIV_H */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
@ -35,24 +35,14 @@
|
|||||||
#include <pios_stm32.h>
|
#include <pios_stm32.h>
|
||||||
|
|
||||||
struct pios_ppm_cfg {
|
struct pios_ppm_cfg {
|
||||||
TIM_TimeBaseInitTypeDef tim_base_init;
|
|
||||||
TIM_ICInitTypeDef tim_ic_init;
|
TIM_ICInitTypeDef tim_ic_init;
|
||||||
GPIO_InitTypeDef gpio_init;
|
const struct pios_tim_channel * channels;
|
||||||
uint32_t remap; /* GPIO_Remap_* */
|
uint8_t num_channels;
|
||||||
struct stm32_irq irq;
|
|
||||||
TIM_TypeDef * timer;
|
|
||||||
GPIO_TypeDef * port;
|
|
||||||
uint16_t ccr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void PIOS_PPM_irq_handler();
|
|
||||||
|
|
||||||
extern uint8_t pios_ppm_num_channels;
|
|
||||||
extern const struct pios_ppm_cfg pios_ppm_cfg;
|
|
||||||
|
|
||||||
extern const struct pios_rcvr_driver pios_ppm_rcvr_driver;
|
extern const struct pios_rcvr_driver pios_ppm_rcvr_driver;
|
||||||
|
|
||||||
extern void PIOS_PPM_Init(void);
|
extern int32_t PIOS_PPM_Init(uint32_t * ppm_id, const struct pios_ppm_cfg * cfg);
|
||||||
|
|
||||||
#endif /* PIOS_PPM_PRIV_H */
|
#endif /* PIOS_PPM_PRIV_H */
|
||||||
|
|
||||||
|
@ -34,32 +34,17 @@
|
|||||||
#include <pios.h>
|
#include <pios.h>
|
||||||
#include <pios_stm32.h>
|
#include <pios_stm32.h>
|
||||||
|
|
||||||
struct pios_pwm_channel {
|
#include <pios_tim_priv.h>
|
||||||
TIM_TypeDef * timer;
|
|
||||||
GPIO_TypeDef * port;
|
|
||||||
uint16_t ccr;
|
|
||||||
uint8_t channel;
|
|
||||||
uint16_t pin;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pios_pwm_cfg {
|
struct pios_pwm_cfg {
|
||||||
TIM_TimeBaseInitTypeDef tim_base_init;
|
|
||||||
TIM_ICInitTypeDef tim_ic_init;
|
TIM_ICInitTypeDef tim_ic_init;
|
||||||
GPIO_InitTypeDef gpio_init;
|
const struct pios_tim_channel * channels;
|
||||||
uint32_t remap; /* GPIO_Remap_* */
|
|
||||||
struct stm32_irq irq;
|
|
||||||
const struct pios_pwm_channel *const channels;
|
|
||||||
uint8_t num_channels;
|
uint8_t num_channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void PIOS_PWM_irq_handler(TIM_TypeDef * timer);
|
|
||||||
|
|
||||||
extern uint8_t pios_pwm_num_channels;
|
|
||||||
extern const struct pios_pwm_cfg pios_pwm_cfg;
|
|
||||||
|
|
||||||
extern const struct pios_rcvr_driver pios_pwm_rcvr_driver;
|
extern const struct pios_rcvr_driver pios_pwm_rcvr_driver;
|
||||||
|
|
||||||
extern void PIOS_PWM_Init(void);
|
extern int32_t PIOS_PWM_Init(uint32_t * pwm_id, const struct pios_pwm_cfg * cfg);
|
||||||
|
|
||||||
#endif /* PIOS_PWM_PRIV_H */
|
#endif /* PIOS_PWM_PRIV_H */
|
||||||
|
|
||||||
|
@ -31,13 +31,6 @@
|
|||||||
#ifndef PIOS_RCVR_H
|
#ifndef PIOS_RCVR_H
|
||||||
#define PIOS_RCVR_H
|
#define PIOS_RCVR_H
|
||||||
|
|
||||||
struct pios_rcvr_channel_map {
|
|
||||||
uint32_t id;
|
|
||||||
uint8_t channel;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[];
|
|
||||||
|
|
||||||
struct pios_rcvr_driver {
|
struct pios_rcvr_driver {
|
||||||
void (*init)(uint32_t id);
|
void (*init)(uint32_t id);
|
||||||
int32_t (*read)(uint32_t id, uint8_t channel);
|
int32_t (*read)(uint32_t id, uint8_t channel);
|
||||||
@ -46,6 +39,16 @@ struct pios_rcvr_driver {
|
|||||||
/* Public Functions */
|
/* Public Functions */
|
||||||
extern int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel);
|
extern int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel);
|
||||||
|
|
||||||
|
/*! Define error codes for PIOS_RCVR_Get */
|
||||||
|
enum PIOS_RCVR_errors {
|
||||||
|
/*! Indicates that a failsafe condition or missing receiver detected for that channel */
|
||||||
|
PIOS_RCVR_TIMEOUT = 0,
|
||||||
|
/*! Channel is invalid for this driver (usually out of range supported) */
|
||||||
|
PIOS_RCVR_INVALID = -1,
|
||||||
|
/*! Indicates that the driver for this channel has not been initialized */
|
||||||
|
PIOS_RCVR_NODRIVER = -2
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* PIOS_RCVR_H */
|
#endif /* PIOS_RCVR_H */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,8 +44,8 @@
|
|||||||
* 1 byte - 0x0f (start of frame byte)
|
* 1 byte - 0x0f (start of frame byte)
|
||||||
* 22 bytes - channel data (11 bit/channel, 16 channels, LSB first)
|
* 22 bytes - channel data (11 bit/channel, 16 channels, LSB first)
|
||||||
* 1 byte - bit flags:
|
* 1 byte - bit flags:
|
||||||
* 0x01 - digital channel 1,
|
* 0x01 - discrete channel 1,
|
||||||
* 0x02 - digital channel 2,
|
* 0x02 - discrete channel 2,
|
||||||
* 0x04 - lost frame flag,
|
* 0x04 - lost frame flag,
|
||||||
* 0x08 - failsafe flag,
|
* 0x08 - failsafe flag,
|
||||||
* 0xf0 - reserved
|
* 0xf0 - reserved
|
||||||
@ -54,16 +54,20 @@
|
|||||||
#define SBUS_FRAME_LENGTH (1+22+1+1)
|
#define SBUS_FRAME_LENGTH (1+22+1+1)
|
||||||
#define SBUS_SOF_BYTE 0x0f
|
#define SBUS_SOF_BYTE 0x0f
|
||||||
#define SBUS_EOF_BYTE 0x00
|
#define SBUS_EOF_BYTE 0x00
|
||||||
#define SBUS_FLAG_DG1 0x01
|
#define SBUS_FLAG_DC1 0x01
|
||||||
#define SBUS_FLAG_DG2 0x02
|
#define SBUS_FLAG_DC2 0x02
|
||||||
#define SBUS_FLAG_FL 0x04
|
#define SBUS_FLAG_FL 0x04
|
||||||
#define SBUS_FLAG_FS 0x08
|
#define SBUS_FLAG_FS 0x08
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* S.Bus protocol provides up to 16 analog and 2 digital channels.
|
* S.Bus protocol provides 16 proportional and 2 discrete channels.
|
||||||
* Only 8 channels are currently supported by the OpenPilot.
|
* Do not change unless driver code is updated accordingly.
|
||||||
*/
|
*/
|
||||||
#define SBUS_NUMBER_OF_CHANNELS 8
|
#define SBUS_NUMBER_OF_CHANNELS (16 + 2)
|
||||||
|
|
||||||
|
/* Discrete channels represented as bits, provide values for them */
|
||||||
|
#define SBUS_VALUE_MIN 352
|
||||||
|
#define SBUS_VALUE_MAX 1696
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* S.Bus configuration programmable invertor
|
* S.Bus configuration programmable invertor
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#define PIOS_SERVO_H
|
#define PIOS_SERVO_H
|
||||||
|
|
||||||
/* Public Functions */
|
/* Public Functions */
|
||||||
extern void PIOS_Servo_Init(void);
|
|
||||||
extern void PIOS_Servo_SetHz(uint16_t * update_rates, uint8_t channels);
|
extern void PIOS_Servo_SetHz(uint16_t * update_rates, uint8_t channels);
|
||||||
extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position);
|
extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position);
|
||||||
|
|
||||||
|
@ -33,25 +33,18 @@
|
|||||||
|
|
||||||
#include <pios.h>
|
#include <pios.h>
|
||||||
#include <pios_stm32.h>
|
#include <pios_stm32.h>
|
||||||
|
#include <pios_tim_priv.h>
|
||||||
struct pios_servo_channel {
|
|
||||||
TIM_TypeDef * timer;
|
|
||||||
GPIO_TypeDef * port;
|
|
||||||
uint8_t channel;
|
|
||||||
uint16_t pin;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pios_servo_cfg {
|
struct pios_servo_cfg {
|
||||||
TIM_TimeBaseInitTypeDef tim_base_init;
|
TIM_TimeBaseInitTypeDef tim_base_init;
|
||||||
TIM_OCInitTypeDef tim_oc_init;
|
TIM_OCInitTypeDef tim_oc_init;
|
||||||
GPIO_InitTypeDef gpio_init;
|
GPIO_InitTypeDef gpio_init;
|
||||||
uint32_t remap;
|
uint32_t remap;
|
||||||
const struct pios_servo_channel *const channels;
|
const struct pios_tim_channel * channels;
|
||||||
uint8_t num_channels;
|
uint8_t num_channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int32_t PIOS_Servo_Init(const struct pios_servo_cfg * cfg);
|
||||||
extern const struct pios_servo_cfg pios_servo_cfg;
|
|
||||||
|
|
||||||
#endif /* PIOS_SERVO_PRIV_H */
|
#endif /* PIOS_SERVO_PRIV_H */
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ extern const struct pios_rcvr_driver pios_spektrum_rcvr_driver;
|
|||||||
|
|
||||||
extern int32_t PIOS_SPEKTRUM_Init(uint32_t * spektrum_id, const struct pios_spektrum_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t bind);
|
extern int32_t PIOS_SPEKTRUM_Init(uint32_t * spektrum_id, const struct pios_spektrum_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t bind);
|
||||||
|
|
||||||
#endif /* PIOS_PWM_PRIV_H */
|
#endif /* PIOS_SPEKTRUM_PRIV_H */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
4
flight/PiOS/inc/pios_tim.h
Normal file
4
flight/PiOS/inc/pios_tim.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef PIOS_TIM_H
|
||||||
|
#define PIOS_TIM_H
|
||||||
|
|
||||||
|
#endif /* PIOS_TIM_H */
|
28
flight/PiOS/inc/pios_tim_priv.h
Normal file
28
flight/PiOS/inc/pios_tim_priv.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef PIOS_TIM_PRIV_H
|
||||||
|
#define PIOS_TIM_PRIV_H
|
||||||
|
|
||||||
|
#include <pios_stm32.h>
|
||||||
|
|
||||||
|
struct pios_tim_clock_cfg {
|
||||||
|
TIM_TypeDef * timer;
|
||||||
|
const TIM_TimeBaseInitTypeDef * time_base_init;
|
||||||
|
struct stm32_irq irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_tim_channel {
|
||||||
|
TIM_TypeDef * timer;
|
||||||
|
uint8_t timer_chan;
|
||||||
|
|
||||||
|
struct stm32_gpio pin;
|
||||||
|
uint32_t remap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pios_tim_callbacks {
|
||||||
|
void (*overflow)(uint32_t tim_id, uint32_t context, uint8_t chan_idx, uint16_t count);
|
||||||
|
void (*edge)(uint32_t tim_id, uint32_t context, uint8_t chan_idx, uint16_t count);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg * cfg);
|
||||||
|
extern int32_t PIOS_TIM_InitChannels(uint32_t * tim_id, const struct pios_tim_channel * channels, uint8_t num_channels, const struct pios_tim_callbacks * callbacks, uint32_t context);
|
||||||
|
|
||||||
|
#endif /* PIOS_TIM_PRIV_H */
|
@ -394,7 +394,7 @@ $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin
|
|||||||
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION)))
|
||||||
|
|
||||||
# Add jtag targets (program and wipe)
|
# Add jtag targets (program and wipe)
|
||||||
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE)))
|
$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG)))
|
||||||
|
|
||||||
.PHONY: elf lss sym hex bin bino opfw
|
.PHONY: elf lss sym hex bin bino opfw
|
||||||
elf: $(OUTDIR)/$(TARGET).elf
|
elf: $(OUTDIR)/$(TARGET).elf
|
||||||
|
75
flight/Project/OpenOCD/stm32f1x.cfg
Normal file
75
flight/Project/OpenOCD/stm32f1x.cfg
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# script for stm32
|
||||||
|
|
||||||
|
if { [info exists CHIPNAME] } {
|
||||||
|
set _CHIPNAME $CHIPNAME
|
||||||
|
} else {
|
||||||
|
set _CHIPNAME stm32
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [info exists ENDIAN] } {
|
||||||
|
set _ENDIAN $ENDIAN
|
||||||
|
} else {
|
||||||
|
set _ENDIAN little
|
||||||
|
}
|
||||||
|
|
||||||
|
# Work-area is a space in RAM used for flash programming
|
||||||
|
# By default use 16kB
|
||||||
|
if { [info exists WORKAREASIZE] } {
|
||||||
|
set _WORKAREASIZE $WORKAREASIZE
|
||||||
|
} else {
|
||||||
|
set _WORKAREASIZE 0x4000
|
||||||
|
}
|
||||||
|
|
||||||
|
# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
|
||||||
|
adapter_khz 1000
|
||||||
|
|
||||||
|
adapter_nsrst_delay 100
|
||||||
|
jtag_ntrst_delay 100
|
||||||
|
|
||||||
|
#jtag scan chain
|
||||||
|
if { [info exists CPUTAPID ] } {
|
||||||
|
set _CPUTAPID $CPUTAPID
|
||||||
|
} else {
|
||||||
|
# See STM Document RM0008
|
||||||
|
# Section 26.6.3
|
||||||
|
set _CPUTAPID 0x3ba00477
|
||||||
|
}
|
||||||
|
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||||
|
|
||||||
|
if { [info exists BSTAPID ] } {
|
||||||
|
# FIXME this never gets used to override defaults...
|
||||||
|
set _BSTAPID $BSTAPID
|
||||||
|
} else {
|
||||||
|
# See STM Document RM0008
|
||||||
|
# Section 29.6.2
|
||||||
|
# Low density devices, Rev A
|
||||||
|
set _BSTAPID1 0x06412041
|
||||||
|
# Medium density devices, Rev A
|
||||||
|
set _BSTAPID2 0x06410041
|
||||||
|
# Medium density devices, Rev B and Rev Z
|
||||||
|
set _BSTAPID3 0x16410041
|
||||||
|
set _BSTAPID4 0x06420041
|
||||||
|
# High density devices, Rev A
|
||||||
|
set _BSTAPID5 0x06414041
|
||||||
|
# Connectivity line devices, Rev A and Rev Z
|
||||||
|
set _BSTAPID6 0x06418041
|
||||||
|
# XL line devices, Rev A
|
||||||
|
set _BSTAPID7 0x06430041
|
||||||
|
}
|
||||||
|
jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \
|
||||||
|
-expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \
|
||||||
|
-expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \
|
||||||
|
-expected-id $_BSTAPID6 -expected-id $_BSTAPID7
|
||||||
|
|
||||||
|
set _TARGETNAME $_CHIPNAME.cpu
|
||||||
|
target create $_TARGETNAME cortex_m3 -endian $_ENDIAN -chain-position $_TARGETNAME -rtos auto
|
||||||
|
|
||||||
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||||
|
|
||||||
|
# flash size will be probed
|
||||||
|
set _FLASHNAME $_CHIPNAME.flash
|
||||||
|
flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME
|
||||||
|
|
||||||
|
# if srst is not fitted use SYSRESETREQ to
|
||||||
|
# perform a soft reset
|
||||||
|
cortex_m3 reset_config sysresetreq
|
61
flight/Project/OpenOCD/stm32f2x.cfg
Normal file
61
flight/Project/OpenOCD/stm32f2x.cfg
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# script for stm32f2xxx
|
||||||
|
|
||||||
|
if { [info exists CHIPNAME] } {
|
||||||
|
set _CHIPNAME $CHIPNAME
|
||||||
|
} else {
|
||||||
|
set _CHIPNAME stm32f2xxx
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [info exists ENDIAN] } {
|
||||||
|
set _ENDIAN $ENDIAN
|
||||||
|
} else {
|
||||||
|
set _ENDIAN little
|
||||||
|
}
|
||||||
|
|
||||||
|
# Work-area is a space in RAM used for flash programming
|
||||||
|
# By default use 64kB
|
||||||
|
if { [info exists WORKAREASIZE] } {
|
||||||
|
set _WORKAREASIZE $WORKAREASIZE
|
||||||
|
} else {
|
||||||
|
set _WORKAREASIZE 0x10000
|
||||||
|
}
|
||||||
|
|
||||||
|
# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
|
||||||
|
#
|
||||||
|
# Since we may be running of an RC oscilator, we crank down the speed a
|
||||||
|
# bit more to be on the safe side. Perhaps superstition, but if are
|
||||||
|
# running off a crystal, we can run closer to the limit. Note
|
||||||
|
# that there can be a pretty wide band where things are more or less stable.
|
||||||
|
jtag_khz 1000
|
||||||
|
|
||||||
|
jtag_nsrst_delay 100
|
||||||
|
jtag_ntrst_delay 100
|
||||||
|
|
||||||
|
#jtag scan chain
|
||||||
|
if { [info exists CPUTAPID ] } {
|
||||||
|
set _CPUTAPID $CPUTAPID
|
||||||
|
} else {
|
||||||
|
# See STM Document RM0033
|
||||||
|
# Section 32.6.3 - corresponds to Cortex-M3 r2p0
|
||||||
|
set _CPUTAPID 0x4ba00477
|
||||||
|
}
|
||||||
|
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||||
|
|
||||||
|
if { [info exists BSTAPID ] } {
|
||||||
|
set _BSTAPID $BSTAPID
|
||||||
|
} else {
|
||||||
|
# See STM Document RM0033
|
||||||
|
# Section 32.6.2
|
||||||
|
#
|
||||||
|
set _BSTAPID 0x06411041
|
||||||
|
}
|
||||||
|
jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID
|
||||||
|
|
||||||
|
set _TARGETNAME $_CHIPNAME.cpu
|
||||||
|
target create $_TARGETNAME cortex_m3 -endian $_ENDIAN -chain-position $_TARGETNAME -rtos auto
|
||||||
|
|
||||||
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||||
|
|
||||||
|
set _FLASHNAME $_CHIPNAME.flash
|
||||||
|
flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME
|
||||||
|
|
@ -91,6 +91,16 @@
|
|||||||
65632DF51251650300469B77 /* pios_board.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_board.h; sourceTree = "<group>"; };
|
65632DF51251650300469B77 /* pios_board.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_board.h; sourceTree = "<group>"; };
|
||||||
65632DF61251650300469B77 /* STM32103CB_AHRS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STM32103CB_AHRS.h; sourceTree = "<group>"; };
|
65632DF61251650300469B77 /* STM32103CB_AHRS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STM32103CB_AHRS.h; sourceTree = "<group>"; };
|
||||||
65632DF71251650300469B77 /* STM3210E_OP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STM3210E_OP.h; sourceTree = "<group>"; };
|
65632DF71251650300469B77 /* STM3210E_OP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STM3210E_OP.h; sourceTree = "<group>"; };
|
||||||
|
65643CAB1413322000A32F59 /* pios_rcvr_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_rcvr_priv.h; sourceTree = "<group>"; };
|
||||||
|
65643CAC1413322000A32F59 /* pios_rcvr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_rcvr.h; sourceTree = "<group>"; };
|
||||||
|
65643CAD1413322000A32F59 /* pios_rtc_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_rtc_priv.h; sourceTree = "<group>"; };
|
||||||
|
65643CAE1413322000A32F59 /* pios_sbus_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_sbus_priv.h; sourceTree = "<group>"; };
|
||||||
|
65643CAF1413322000A32F59 /* pios_sbus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_sbus.h; sourceTree = "<group>"; };
|
||||||
|
65643CB01413322000A32F59 /* pios_spektrum_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_spektrum_priv.h; sourceTree = "<group>"; };
|
||||||
|
65643CB91413456D00A32F59 /* pios_tim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_tim.c; sourceTree = "<group>"; };
|
||||||
|
65643CBA141350C200A32F59 /* pios_sbus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_sbus.c; sourceTree = "<group>"; };
|
||||||
|
65643CEC141429A100A32F59 /* NMEA.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = NMEA.c; sourceTree = "<group>"; };
|
||||||
|
65643CEE141429AF00A32F59 /* NMEA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMEA.h; sourceTree = "<group>"; };
|
||||||
6572CB1613D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_memory.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = link_STM32103CB_CC_Rev1_memory.ld; path = ../../PiOS/STM32F10x/link_STM32103CB_CC_Rev1_memory.ld; sourceTree = SOURCE_ROOT; };
|
6572CB1613D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_memory.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = link_STM32103CB_CC_Rev1_memory.ld; path = ../../PiOS/STM32F10x/link_STM32103CB_CC_Rev1_memory.ld; sourceTree = SOURCE_ROOT; };
|
||||||
6572CB1713D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_sections.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = link_STM32103CB_CC_Rev1_sections.ld; path = ../../PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld; sourceTree = SOURCE_ROOT; };
|
6572CB1713D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_sections.ld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = link_STM32103CB_CC_Rev1_sections.ld; path = ../../PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld; sourceTree = SOURCE_ROOT; };
|
||||||
657CEEAD121DB6C8007A1FBE /* homelocation.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = homelocation.xml; sourceTree = "<group>"; };
|
657CEEAD121DB6C8007A1FBE /* homelocation.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = homelocation.xml; sourceTree = "<group>"; };
|
||||||
@ -7724,11 +7734,17 @@
|
|||||||
65E8F04811EFF25C00BBF654 /* pios_ppm.h */,
|
65E8F04811EFF25C00BBF654 /* pios_ppm.h */,
|
||||||
65E8F04911EFF25C00BBF654 /* pios_pwm.h */,
|
65E8F04911EFF25C00BBF654 /* pios_pwm.h */,
|
||||||
657FF86A12EA8BFB00801617 /* pios_pwm_priv.h */,
|
657FF86A12EA8BFB00801617 /* pios_pwm_priv.h */,
|
||||||
|
65643CAC1413322000A32F59 /* pios_rcvr.h */,
|
||||||
|
65643CAB1413322000A32F59 /* pios_rcvr_priv.h */,
|
||||||
6589A9E2131DF1C7006BD67C /* pios_rtc.h */,
|
6589A9E2131DF1C7006BD67C /* pios_rtc.h */,
|
||||||
|
65643CAD1413322000A32F59 /* pios_rtc_priv.h */,
|
||||||
|
65643CAE1413322000A32F59 /* pios_sbus_priv.h */,
|
||||||
|
65643CAF1413322000A32F59 /* pios_sbus.h */,
|
||||||
65E8F04A11EFF25C00BBF654 /* pios_sdcard.h */,
|
65E8F04A11EFF25C00BBF654 /* pios_sdcard.h */,
|
||||||
65E8F04B11EFF25C00BBF654 /* pios_servo.h */,
|
65E8F04B11EFF25C00BBF654 /* pios_servo.h */,
|
||||||
65FBE14412E7C98100176B5A /* pios_servo_priv.h */,
|
65FBE14412E7C98100176B5A /* pios_servo_priv.h */,
|
||||||
65E8F04C11EFF25C00BBF654 /* pios_spektrum.h */,
|
65E8F04C11EFF25C00BBF654 /* pios_spektrum.h */,
|
||||||
|
65643CB01413322000A32F59 /* pios_spektrum_priv.h */,
|
||||||
65E8F04D11EFF25C00BBF654 /* pios_spi.h */,
|
65E8F04D11EFF25C00BBF654 /* pios_spi.h */,
|
||||||
65E8F04E11EFF25C00BBF654 /* pios_spi_priv.h */,
|
65E8F04E11EFF25C00BBF654 /* pios_spi_priv.h */,
|
||||||
65E8F04F11EFF25C00BBF654 /* pios_stm32.h */,
|
65E8F04F11EFF25C00BBF654 /* pios_stm32.h */,
|
||||||
@ -7752,6 +7768,24 @@
|
|||||||
65E8F05811EFF25C00BBF654 /* STM32F10x */ = {
|
65E8F05811EFF25C00BBF654 /* STM32F10x */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
65D1FBD813F51865006374A6 /* pios_bmp085.c */,
|
||||||
|
6560A39D13EE277E00105DA5 /* pios_iap.c */,
|
||||||
|
6560A39E13EE277E00105DA5 /* pios_sbus.c */,
|
||||||
|
6560A38E13EE270C00105DA5 /* link_STM3210E_INS_BL_sections.ld */,
|
||||||
|
6560A38F13EE270C00105DA5 /* link_STM3210E_INS_memory.ld */,
|
||||||
|
6560A39013EE270C00105DA5 /* link_STM3210E_INS_sections.ld */,
|
||||||
|
6560A39113EE270C00105DA5 /* link_STM3210E_OP_BL_sections.ld */,
|
||||||
|
6560A39213EE270C00105DA5 /* link_STM3210E_OP_memory.ld */,
|
||||||
|
6560A39313EE270C00105DA5 /* link_STM3210E_OP_sections.ld */,
|
||||||
|
6560A39413EE270C00105DA5 /* link_STM32103CB_AHRS_BL_sections.ld */,
|
||||||
|
6560A39513EE270C00105DA5 /* link_STM32103CB_AHRS_memory.ld */,
|
||||||
|
6560A39613EE270C00105DA5 /* link_STM32103CB_AHRS_sections.ld */,
|
||||||
|
6560A39713EE270C00105DA5 /* link_STM32103CB_CC_Rev1_BL_sections.ld */,
|
||||||
|
6572CB1613D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_memory.ld */,
|
||||||
|
6572CB1713D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_sections.ld */,
|
||||||
|
6560A39813EE270C00105DA5 /* link_STM32103CB_PIPXTREME_BL_sections.ld */,
|
||||||
|
6560A39913EE270C00105DA5 /* link_STM32103CB_PIPXTREME_memory.ld */,
|
||||||
|
6560A39A13EE270C00105DA5 /* link_STM32103CB_PIPXTREME_sections.ld */,
|
||||||
65E8F05911EFF25C00BBF654 /* Libraries */,
|
65E8F05911EFF25C00BBF654 /* Libraries */,
|
||||||
65E8F0D811EFF25C00BBF654 /* link_stm32f10x_HD.ld */,
|
65E8F0D811EFF25C00BBF654 /* link_stm32f10x_HD.ld */,
|
||||||
65E8F0DB11EFF25C00BBF654 /* link_stm32f10x_MD.ld */,
|
65E8F0DB11EFF25C00BBF654 /* link_stm32f10x_MD.ld */,
|
||||||
@ -7766,10 +7800,12 @@
|
|||||||
65E8F0E411EFF25C00BBF654 /* pios_ppm.c */,
|
65E8F0E411EFF25C00BBF654 /* pios_ppm.c */,
|
||||||
65E8F0E511EFF25C00BBF654 /* pios_pwm.c */,
|
65E8F0E511EFF25C00BBF654 /* pios_pwm.c */,
|
||||||
6589A9DB131DEE76006BD67C /* pios_rtc.c */,
|
6589A9DB131DEE76006BD67C /* pios_rtc.c */,
|
||||||
|
65643CBA141350C200A32F59 /* pios_sbus.c */,
|
||||||
65E8F0E611EFF25C00BBF654 /* pios_servo.c */,
|
65E8F0E611EFF25C00BBF654 /* pios_servo.c */,
|
||||||
65E8F0E711EFF25C00BBF654 /* pios_spektrum.c */,
|
65E8F0E711EFF25C00BBF654 /* pios_spektrum.c */,
|
||||||
65E8F0E811EFF25C00BBF654 /* pios_spi.c */,
|
65E8F0E811EFF25C00BBF654 /* pios_spi.c */,
|
||||||
65E8F0E911EFF25C00BBF654 /* pios_sys.c */,
|
65E8F0E911EFF25C00BBF654 /* pios_sys.c */,
|
||||||
|
65643CB91413456D00A32F59 /* pios_tim.c */,
|
||||||
65E8F0EA11EFF25C00BBF654 /* pios_usart.c */,
|
65E8F0EA11EFF25C00BBF654 /* pios_usart.c */,
|
||||||
65E8F0ED11EFF25C00BBF654 /* pios_usb_hid.c */,
|
65E8F0ED11EFF25C00BBF654 /* pios_usb_hid.c */,
|
||||||
651CF9E5120B5D8300EEFD70 /* pios_usb_hid_desc.c */,
|
651CF9E5120B5D8300EEFD70 /* pios_usb_hid_desc.c */,
|
||||||
@ -7787,8 +7823,6 @@
|
|||||||
65E8F05911EFF25C00BBF654 /* Libraries */ = {
|
65E8F05911EFF25C00BBF654 /* Libraries */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6572CB1613D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_memory.ld */,
|
|
||||||
6572CB1713D0F2B200FC2972 /* link_STM32103CB_CC_Rev1_sections.ld */,
|
|
||||||
65E8F05A11EFF25C00BBF654 /* CMSIS */,
|
65E8F05A11EFF25C00BBF654 /* CMSIS */,
|
||||||
65E8F06B11EFF25C00BBF654 /* dosfs */,
|
65E8F06B11EFF25C00BBF654 /* dosfs */,
|
||||||
65E8F07111EFF25C00BBF654 /* FreeRTOS */,
|
65E8F07111EFF25C00BBF654 /* FreeRTOS */,
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
# Generate a version blob for
|
|
||||||
# the OpenPilot firmware.
|
|
||||||
#
|
|
||||||
# By E. Lafargue (c) 2011 E. Lafargue & the OpenPilot team
|
|
||||||
# Licence: GPLv3
|
|
||||||
#
|
|
||||||
###
|
|
||||||
# Usage:
|
|
||||||
# versionblob.py --append --firmware=<Firmware file name> --boardid=<Board code>
|
|
||||||
#
|
|
||||||
# append: if present, then append blob to firmware file directly, otherwise create "blob.bin"
|
|
||||||
# firmware: the filename of the firmware binary
|
|
||||||
# boardid: as a string, the board code, for example "0401" for CC board version 1.
|
|
||||||
# should match the codes in firmware description files.
|
|
||||||
#
|
|
||||||
# We have 100 bytes for the whole description.
|
|
||||||
#
|
|
||||||
# Only the first 40 are visible on the FirmwareIAP uavobject, the remaining
|
|
||||||
# 60 are ok to use for packaging and will be saved in the flash
|
|
||||||
#
|
|
||||||
# Structure is:
|
|
||||||
# 4 bytes: header: "OpFw"
|
|
||||||
# 4 bytes: GIT commit tag (short version of SHA1)
|
|
||||||
# 4 bytes: Unix timestamp of compile time
|
|
||||||
# 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files.
|
|
||||||
# 26 bytes: commit tag if it is there, otherwise branch name. Zero-padded
|
|
||||||
# ---- 40 bytes limit ---
|
|
||||||
# 20 bytes: SHA1 sum of the firmware.
|
|
||||||
# 40 bytes: free for now.
|
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
|
||||||
from time import time
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
# Do the argument parsing:
|
|
||||||
parser = argparse.ArgumentParser(description='Generate firmware desciption blob')
|
|
||||||
parser.add_argument('--append', action='store_true')
|
|
||||||
parser.add_argument('--firmware', help='name of firmware binary file' , required=True)
|
|
||||||
parser.add_argument('--boardid', help='ID of board model, for example 0401 for CopterControl', required=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
print args
|
|
||||||
|
|
||||||
if args.append == True:
|
|
||||||
print 'Appending description blob directly to ' + args.firmware
|
|
||||||
filename = args.firmware
|
|
||||||
file = open(filename,"ab")
|
|
||||||
else:
|
|
||||||
filename = 'blob.bin'
|
|
||||||
file = open(filename,"wb")
|
|
||||||
|
|
||||||
|
|
||||||
# Write the magic value:
|
|
||||||
file.write("OpFw")
|
|
||||||
# Get the short commit tag of the current git repository.
|
|
||||||
# Strip it to 8 characters for a 4 byte (int32) value.
|
|
||||||
# We have no full guarantee of unicity, but it is good enough
|
|
||||||
# with the rest of the information in the structure.
|
|
||||||
hs= os.popen('git rev-parse --short=8 HEAD').read().strip()
|
|
||||||
print "Version: " + hs
|
|
||||||
hb=binascii.a2b_hex(hs)
|
|
||||||
file.write(hb)
|
|
||||||
# Then the Unix time into a 32 bit integer:
|
|
||||||
print "Date: " + hex(int(time())).lstrip('0x')
|
|
||||||
hb = binascii.a2b_hex(hex(int(time())).lstrip('0x'))
|
|
||||||
file.write(hb)
|
|
||||||
|
|
||||||
# Then write board type and board revision
|
|
||||||
hb = binascii.a2b_hex(args.boardid)
|
|
||||||
file.write(hb)
|
|
||||||
|
|
||||||
# Last: a user-friendly description if it exists in GIT, otherwise
|
|
||||||
# just "unreleased"
|
|
||||||
hs = os.popen('git describe --exact-match').read()
|
|
||||||
if len(hs) == 0 :
|
|
||||||
print "Unreleased: get branch name instead"
|
|
||||||
hs = os.popen('git branch --contains HEAD').read()
|
|
||||||
|
|
||||||
file.write(hs[0:26])
|
|
||||||
file.write("\0"*(26-len(hs)))
|
|
||||||
|
|
||||||
## Now we are at the 40 bytes mark.
|
|
||||||
|
|
||||||
## Add the 20 byte SHA1 hash of the firmware:
|
|
||||||
import hashlib
|
|
||||||
sha1 = hashlib.sha1()
|
|
||||||
with open('build/coptercontrol/CopterControl.bin','rb') as f:
|
|
||||||
for chunk in iter(lambda: f.read(8192), ''):
|
|
||||||
sha1.update(chunk)
|
|
||||||
file.write(sha1.digest())
|
|
||||||
|
|
||||||
# Pad will null bytes:
|
|
||||||
file.write('\0'*40)
|
|
||||||
|
|
||||||
|
|
||||||
file.close()
|
|
||||||
|
|
@ -65,7 +65,7 @@ MyTabbedStackWidget::MyTabbedStackWidget(QWidget *parent, bool isVertical, bool
|
|||||||
m_stackWidget->setContentsMargins(0, 0, 0, 0);
|
m_stackWidget->setContentsMargins(0, 0, 0, 0);
|
||||||
setLayout(toplevelLayout);
|
setLayout(toplevelLayout);
|
||||||
|
|
||||||
connect(m_listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(showWidget(int)));
|
connect(m_listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(showWidget(int)),Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon &icon, const QString &label)
|
void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon &icon, const QString &label)
|
||||||
@ -97,9 +97,19 @@ void MyTabbedStackWidget::setCurrentIndex(int index)
|
|||||||
|
|
||||||
void MyTabbedStackWidget::showWidget(int index)
|
void MyTabbedStackWidget::showWidget(int index)
|
||||||
{
|
{
|
||||||
emit currentAboutToShow(index);
|
if(m_stackWidget->currentIndex()==index)
|
||||||
m_stackWidget->setCurrentIndex(index);
|
return;
|
||||||
emit currentChanged(index);
|
bool proceed=false;
|
||||||
|
emit currentAboutToShow(index,&proceed);
|
||||||
|
if(proceed)
|
||||||
|
{
|
||||||
|
m_stackWidget->setCurrentIndex(index);
|
||||||
|
emit currentChanged(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_listWidget->setCurrentRow(m_stackWidget->currentIndex(),QItemSelectionModel::ClearAndSelect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyTabbedStackWidget::insertCornerWidget(int index, QWidget *widget)
|
void MyTabbedStackWidget::insertCornerWidget(int index, QWidget *widget)
|
||||||
|
@ -51,9 +51,10 @@ public:
|
|||||||
|
|
||||||
void insertCornerWidget(int index, QWidget *widget);
|
void insertCornerWidget(int index, QWidget *widget);
|
||||||
int cornerWidgetCount() { return m_cornerWidgetCount; }
|
int cornerWidgetCount() { return m_cornerWidgetCount; }
|
||||||
|
QWidget * currentWidget(){return m_stackWidget->currentWidget();}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentAboutToShow(int index);
|
void currentAboutToShow(int index,bool * proceed);
|
||||||
void currentChanged(int index);
|
void currentChanged(int index);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Receiver type</string>
|
<string>RcvrPort</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QComboBox" name="receiverType"/>
|
<widget class="QComboBox" name="cbRcvr"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>2</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="BasicTab">
|
<widget class="QWidget" name="BasicTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -880,7 +880,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QCheckBox" name="ccpmLinkRoll">
|
<widget class="QCheckBox" name="ccpmLinkRoll">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Link Roll/Pitch</string>
|
<string>Link Roll/Pitch</string>
|
||||||
@ -890,7 +890,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QCheckBox" name="ccpmLinkCyclic">
|
<widget class="QCheckBox" name="ccpmLinkCyclic">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Link Cyclic/Collective</string>
|
<string>Link Cyclic/Collective</string>
|
||||||
@ -900,80 +900,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
|
||||||
<layout class="QHBoxLayout" name="ccpmCollectiveChannelBox">
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetNoConstraint</enum>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="ccpmCollectiveChLabel">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>11</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Collective Ch</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="ccpmCollectiveChannel">
|
|
||||||
<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>90</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -38,6 +38,7 @@ HEADERS += configplugin.h \
|
|||||||
defaultattitudewidget.h \
|
defaultattitudewidget.h \
|
||||||
smartsavebutton.h \
|
smartsavebutton.h \
|
||||||
defaulthwsettingswidget.h \
|
defaulthwsettingswidget.h \
|
||||||
|
inputchannelform.h \
|
||||||
configcamerastabilizationwidget.h
|
configcamerastabilizationwidget.h
|
||||||
|
|
||||||
SOURCES += configplugin.cpp \
|
SOURCES += configplugin.cpp \
|
||||||
@ -67,6 +68,7 @@ SOURCES += configplugin.cpp \
|
|||||||
defaultattitudewidget.cpp \
|
defaultattitudewidget.cpp \
|
||||||
smartsavebutton.cpp \
|
smartsavebutton.cpp \
|
||||||
defaulthwsettingswidget.cpp \
|
defaulthwsettingswidget.cpp \
|
||||||
|
inputchannelform.cpp \
|
||||||
configcamerastabilizationwidget.cpp
|
configcamerastabilizationwidget.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
@ -81,6 +83,7 @@ FORMS += \
|
|||||||
ccattitude.ui \
|
ccattitude.ui \
|
||||||
defaultattitude.ui \
|
defaultattitude.ui \
|
||||||
defaulthwsettings.ui \
|
defaulthwsettings.ui \
|
||||||
|
inputchannelform.ui \
|
||||||
camerastabilization.ui
|
camerastabilization.ui
|
||||||
|
|
||||||
RESOURCES += configgadget.qrc
|
RESOURCES += configgadget.qrc
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configtelemetrywidget.h
|
* @file configtelemetrywidget.h
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
@ -43,7 +43,7 @@ ConfigCCHWWidget::ConfigCCHWWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|||||||
addUAVObjectToWidgetRelation("TelemetrySettings","Speed",m_telemetry->telemetrySpeed);
|
addUAVObjectToWidgetRelation("TelemetrySettings","Speed",m_telemetry->telemetrySpeed);
|
||||||
addUAVObjectToWidgetRelation("HwSettings","CC_FlexiPort",m_telemetry->cbFlexi);
|
addUAVObjectToWidgetRelation("HwSettings","CC_FlexiPort",m_telemetry->cbFlexi);
|
||||||
addUAVObjectToWidgetRelation("HwSettings","CC_MainPort",m_telemetry->cbTele);
|
addUAVObjectToWidgetRelation("HwSettings","CC_MainPort",m_telemetry->cbTele);
|
||||||
addUAVObjectToWidgetRelation("ManualControlSettings","InputMode",m_telemetry->receiverType);
|
addUAVObjectToWidgetRelation("HwSettings","CC_RcvrPort",m_telemetry->cbRcvr);
|
||||||
connect(m_telemetry->cchwHelp,SIGNAL(clicked()),this,SLOT(openHelp()));
|
connect(m_telemetry->cchwHelp,SIGNAL(clicked()),this,SLOT(openHelp()));
|
||||||
enableControls(false);
|
enableControls(false);
|
||||||
populateWidgets();
|
populateWidgets();
|
||||||
@ -67,22 +67,6 @@ void ConfigCCHWWidget::widgetsContentsChanged()
|
|||||||
{
|
{
|
||||||
m_telemetry->problems->setText("Warning: you have configured the MainPort and the FlexiPort for the same function, this is currently not suported");
|
m_telemetry->problems->setText("Warning: you have configured the MainPort and the FlexiPort for the same function, this is currently not suported");
|
||||||
}
|
}
|
||||||
else if((m_telemetry->cbTele->currentText()=="Spektrum" ||m_telemetry->cbFlexi->currentText()=="Spektrum") && m_telemetry->receiverType->currentText()!="Spektrum")
|
|
||||||
{
|
|
||||||
m_telemetry->problems->setText("Warning: you have a port configured as 'Spektrum' however that is not your selected receiver type");
|
|
||||||
}
|
|
||||||
else if(m_telemetry->cbTele->currentText()=="S.Bus" && m_telemetry->receiverType->currentText()!="S.Bus")
|
|
||||||
{
|
|
||||||
m_telemetry->problems->setText("Warning: you have a port configured as 'S.Bus' however that is not your selected receiver type");
|
|
||||||
}
|
|
||||||
else if(m_telemetry->cbTele->currentText()!="S.Bus" && m_telemetry->receiverType->currentText()=="S.Bus")
|
|
||||||
{
|
|
||||||
m_telemetry->problems->setText("Warning: you have selected 'S.Bus' as your receiver type however you have no port configured for that protocol");
|
|
||||||
}
|
|
||||||
else if((m_telemetry->cbTele->currentText()!="Spektrum" && m_telemetry->cbFlexi->currentText()!="Spektrum") && m_telemetry->receiverType->currentText()=="Spektrum")
|
|
||||||
{
|
|
||||||
m_telemetry->problems->setText("Warning: you have selected 'Spektrum' as your receiver type however you have no port configured for that protocol");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_telemetry->problems->setText("");
|
m_telemetry->problems->setText("");
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configtelemetrywidget.h
|
* @file configtelemetrywidget.h
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
|
@ -92,26 +92,7 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
|||||||
m_aircraft->setupUi(this);
|
m_aircraft->setupUi(this);
|
||||||
|
|
||||||
setupButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
setupButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
||||||
addWidget(m_aircraft->customMixerTable);
|
|
||||||
addWidget(m_aircraft->customThrottle2Curve);
|
|
||||||
addWidget(m_aircraft->customThrottle1Curve);
|
|
||||||
addWidget(m_aircraft->multiThrottleCurve);
|
|
||||||
addWidget(m_aircraft->fixedWingThrottle);
|
|
||||||
addWidget(m_aircraft->fixedWingType);
|
|
||||||
addWidget(m_aircraft->feedForwardSlider);
|
|
||||||
addWidget(m_aircraft->accelTime);
|
|
||||||
addWidget(m_aircraft->decelTime);
|
|
||||||
addWidget(m_aircraft->maxAccelSlider);
|
|
||||||
addWidget(m_aircraft->multirotorFrameType);
|
|
||||||
addWidget(m_aircraft->multiMotor1);
|
|
||||||
addWidget(m_aircraft->multiMotor2);
|
|
||||||
addWidget(m_aircraft->multiMotor3);
|
|
||||||
addWidget(m_aircraft->multiMotor4);
|
|
||||||
addWidget(m_aircraft->multiMotor5);
|
|
||||||
addWidget(m_aircraft->multiMotor6);
|
|
||||||
addWidget(m_aircraft->multiMotor7);
|
|
||||||
addWidget(m_aircraft->multiMotor8);
|
|
||||||
addWidget(m_aircraft->triYawChannel);
|
|
||||||
addUAVObject("SystemSettings");
|
addUAVObject("SystemSettings");
|
||||||
addUAVObject("MixerSettings");
|
addUAVObject("MixerSettings");
|
||||||
addUAVObject("ActuatorSettings");
|
addUAVObject("ActuatorSettings");
|
||||||
@ -217,7 +198,7 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
|||||||
|
|
||||||
// Connect the help button
|
// Connect the help button
|
||||||
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
|
addToDirtyMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigAirframeWidget::~ConfigAirframeWidget()
|
ConfigAirframeWidget::~ConfigAirframeWidget()
|
||||||
@ -462,6 +443,7 @@ void ConfigAirframeWidget::updateCustomThrottle2CurveValue(QList<double> list, d
|
|||||||
*/
|
*/
|
||||||
void ConfigAirframeWidget::refreshWidgetsValues()
|
void ConfigAirframeWidget::refreshWidgetsValues()
|
||||||
{
|
{
|
||||||
|
bool dirty=isDirty();
|
||||||
// Get the Airframe type from the system settings:
|
// Get the Airframe type from the system settings:
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||||
Q_ASSERT(obj);
|
Q_ASSERT(obj);
|
||||||
@ -913,6 +895,7 @@ void ConfigAirframeWidget::refreshWidgetsValues()
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCustomAirframeUI();
|
updateCustomAirframeUI();
|
||||||
|
setDirty(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -921,6 +904,7 @@ void ConfigAirframeWidget::refreshWidgetsValues()
|
|||||||
*/
|
*/
|
||||||
void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||||
{
|
{
|
||||||
|
bool dirty=isDirty();
|
||||||
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||||
// Setup the UI
|
// Setup the UI
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
@ -1118,6 +1102,7 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
|||||||
}
|
}
|
||||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
||||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||||
|
setDirty(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2139,3 +2124,77 @@ void ConfigAirframeWidget::openHelp()
|
|||||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigAirframeWidget::addToDirtyMonitor()
|
||||||
|
{
|
||||||
|
addWidget(m_aircraft->customMixerTable);
|
||||||
|
addWidget(m_aircraft->customThrottle2Curve);
|
||||||
|
addWidget(m_aircraft->customThrottle1Curve);
|
||||||
|
addWidget(m_aircraft->multiThrottleCurve);
|
||||||
|
addWidget(m_aircraft->fixedWingThrottle);
|
||||||
|
addWidget(m_aircraft->fixedWingType);
|
||||||
|
addWidget(m_aircraft->feedForwardSlider);
|
||||||
|
addWidget(m_aircraft->accelTime);
|
||||||
|
addWidget(m_aircraft->decelTime);
|
||||||
|
addWidget(m_aircraft->maxAccelSlider);
|
||||||
|
addWidget(m_aircraft->multirotorFrameType);
|
||||||
|
addWidget(m_aircraft->multiMotor1);
|
||||||
|
addWidget(m_aircraft->multiMotor2);
|
||||||
|
addWidget(m_aircraft->multiMotor3);
|
||||||
|
addWidget(m_aircraft->multiMotor4);
|
||||||
|
addWidget(m_aircraft->multiMotor5);
|
||||||
|
addWidget(m_aircraft->multiMotor6);
|
||||||
|
addWidget(m_aircraft->multiMotor7);
|
||||||
|
addWidget(m_aircraft->multiMotor8);
|
||||||
|
addWidget(m_aircraft->triYawChannel);
|
||||||
|
addWidget(m_aircraft->aircraftType);
|
||||||
|
addWidget(m_aircraft->fwEngineChannel);
|
||||||
|
addWidget(m_aircraft->fwAileron1Channel);
|
||||||
|
addWidget(m_aircraft->fwAileron2Channel);
|
||||||
|
addWidget(m_aircraft->fwElevator1Channel);
|
||||||
|
addWidget(m_aircraft->fwElevator2Channel);
|
||||||
|
addWidget(m_aircraft->fwRudder1Channel);
|
||||||
|
addWidget(m_aircraft->fwRudder2Channel);
|
||||||
|
addWidget(m_aircraft->elevonSlider1);
|
||||||
|
addWidget(m_aircraft->elevonSlider2);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmType);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->TabObject);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmTailChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmEngineChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoWChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoXChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoYChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmSingleServo);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoZChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleW);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleX);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCorrectionAngle);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleZ);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleY);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivePassthrough);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkRoll);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkCyclic);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRevoSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmREVOspinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivespinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCyclicScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSpinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveType);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->NumCurvePoints);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue1);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue2);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue3);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveToGenerate);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveSettings);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ThrottleCurve);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->PitchCurve);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAdvancedSettingsTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ private:
|
|||||||
void updateCustomAirframeUI();
|
void updateCustomAirframeUI();
|
||||||
bool setupMixer(double mixerFactors[8][3]);
|
bool setupMixer(double mixerFactors[8][3]);
|
||||||
void setupMotors(QList<QString> motorList);
|
void setupMotors(QList<QString> motorList);
|
||||||
|
void addToDirtyMonitor();
|
||||||
void resetField(UAVObjectField * field);
|
void resetField(UAVObjectField * field);
|
||||||
void resetMixer (MixerCurveWidget *mixer, int numElements, double maxvalue);
|
void resetMixer (MixerCurveWidget *mixer, int numElements, double maxvalue);
|
||||||
void resetActuators();
|
void resetActuators();
|
||||||
|
@ -40,22 +40,19 @@ ConfigCCAttitudeWidget::ConfigCCAttitudeWidget(QWidget *parent) :
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
connect(ui->zeroBias,SIGNAL(clicked()),this,SLOT(startAccelCalibration()));
|
connect(ui->zeroBias,SIGNAL(clicked()),this,SLOT(startAccelCalibration()));
|
||||||
connect(ui->saveButton,SIGNAL(clicked()),this,SLOT(saveAttitudeSettings()));
|
|
||||||
connect(ui->applyButton,SIGNAL(clicked()),this,SLOT(applyAttitudeSettings()));
|
|
||||||
|
|
||||||
// Make it smart:
|
|
||||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect()));
|
|
||||||
connect(parent, SIGNAL(autopilotDisconnected()), this, SLOT(onAutopilotDisconnect()));
|
|
||||||
|
|
||||||
enableControls(true);
|
setupButtons(ui->applyButton,ui->saveButton);
|
||||||
refreshValues(); // The 1st time this panel is instanciated, the autopilot is already connected.
|
addUAVObject("AttitudeSettings");
|
||||||
UAVObject * settings = AttitudeSettings::GetInstance(getObjectManager());
|
|
||||||
connect(settings,SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshValues()));
|
|
||||||
|
|
||||||
// Connect the help button
|
// Connect the help button
|
||||||
connect(ui->ccAttitudeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
connect(ui->ccAttitudeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
|
addUAVObjectToWidgetRelation("AttitudeSettings","ZeroDuringArming",ui->zeroGyroBiasOnArming);
|
||||||
|
|
||||||
|
addUAVObjectToWidgetRelation("AttitudeSettings","BoardRotation",ui->rollBias,AttitudeSettings::BOARDROTATION_ROLL);
|
||||||
|
addUAVObjectToWidgetRelation("AttitudeSettings","BoardRotation",ui->pitchBias,AttitudeSettings::BOARDROTATION_PITCH);
|
||||||
|
addUAVObjectToWidgetRelation("AttitudeSettings","BoardRotation",ui->yawBias,AttitudeSettings::BOARDROTATION_YAW);
|
||||||
|
addWidget(ui->zeroBias);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigCCAttitudeWidget::~ConfigCCAttitudeWidget()
|
ConfigCCAttitudeWidget::~ConfigCCAttitudeWidget()
|
||||||
@ -63,12 +60,6 @@ ConfigCCAttitudeWidget::~ConfigCCAttitudeWidget()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::enableControls(bool enable)
|
|
||||||
{
|
|
||||||
//ui->applyButton->setEnabled(enable);
|
|
||||||
ui->saveButton->setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::attitudeRawUpdated(UAVObject * obj) {
|
void ConfigCCAttitudeWidget::attitudeRawUpdated(UAVObject * obj) {
|
||||||
QMutexLocker locker(&startStop);
|
QMutexLocker locker(&startStop);
|
||||||
|
|
||||||
@ -130,26 +121,6 @@ void ConfigCCAttitudeWidget::timeout() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::applyAttitudeSettings() {
|
|
||||||
AttitudeSettings::DataFields attitudeSettingsData = AttitudeSettings::GetInstance(getObjectManager())->getData();
|
|
||||||
attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL] = ui->rollBias->value();
|
|
||||||
attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH] = ui->pitchBias->value();
|
|
||||||
attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] = ui->yawBias->value();
|
|
||||||
attitudeSettingsData.ZeroDuringArming = ui->zeroGyroBiasOnArming->isChecked() ? AttitudeSettings::ZERODURINGARMING_TRUE :
|
|
||||||
AttitudeSettings::ZERODURINGARMING_FALSE;
|
|
||||||
AttitudeSettings::GetInstance(getObjectManager())->setData(attitudeSettingsData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::refreshValues() {
|
|
||||||
AttitudeSettings::DataFields attitudeSettingsData = AttitudeSettings::GetInstance(getObjectManager())->getData();
|
|
||||||
|
|
||||||
ui->rollBias->setValue(attitudeSettingsData.BoardRotation[0]);
|
|
||||||
ui->pitchBias->setValue(attitudeSettingsData.BoardRotation[1]);
|
|
||||||
ui->yawBias->setValue(attitudeSettingsData.BoardRotation[2]);
|
|
||||||
ui->zeroGyroBiasOnArming->setChecked(attitudeSettingsData.ZeroDuringArming == AttitudeSettings::ZERODURINGARMING_TRUE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::startAccelCalibration() {
|
void ConfigCCAttitudeWidget::startAccelCalibration() {
|
||||||
QMutexLocker locker(&startStop);
|
QMutexLocker locker(&startStop);
|
||||||
|
|
||||||
@ -184,16 +155,16 @@ void ConfigCCAttitudeWidget::startAccelCalibration() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::saveAttitudeSettings() {
|
|
||||||
applyAttitudeSettings();
|
|
||||||
|
|
||||||
UAVDataObject * obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("AttitudeSettings")));
|
|
||||||
saveObjectToSD(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigCCAttitudeWidget::openHelp()
|
void ConfigCCAttitudeWidget::openHelp()
|
||||||
{
|
{
|
||||||
|
|
||||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/CopterControl+Attitude+Configuration", QUrl::StrictMode) );
|
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/CopterControl+Attitude+Configuration", QUrl::StrictMode) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigCCAttitudeWidget::enableControls(bool enable)
|
||||||
|
{
|
||||||
|
if(ui->zeroBias)
|
||||||
|
ui->zeroBias->setEnabled(enable);
|
||||||
|
ConfigTaskWidget::enableControls(enable);
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -50,9 +50,6 @@ private slots:
|
|||||||
void attitudeRawUpdated(UAVObject * obj);
|
void attitudeRawUpdated(UAVObject * obj);
|
||||||
void timeout();
|
void timeout();
|
||||||
void startAccelCalibration();
|
void startAccelCalibration();
|
||||||
void saveAttitudeSettings();
|
|
||||||
void applyAttitudeSettings();
|
|
||||||
virtual void refreshValues();
|
|
||||||
void openHelp();
|
void openHelp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -69,6 +66,7 @@ private:
|
|||||||
|
|
||||||
static const int NUM_ACCEL_UPDATES = 60;
|
static const int NUM_ACCEL_UPDATES = 60;
|
||||||
static const float ACCEL_SCALE = 0.004f * 9.81f;
|
static const float ACCEL_SCALE = 0.004f * 9.81f;
|
||||||
|
protected:
|
||||||
virtual void enableControls(bool enable);
|
virtual void enableControls(bool enable);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "mixersettings.h"
|
#include "mixersettings.h"
|
||||||
#include "systemsettings.h"
|
#include "systemsettings.h"
|
||||||
|
#include "actuatorcommand.h"
|
||||||
|
|
||||||
#define Pi 3.14159265358979323846
|
#define Pi 3.14159265358979323846
|
||||||
|
|
||||||
@ -70,8 +71,6 @@ ConfigccpmWidget::ConfigccpmWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|||||||
m_ccpm->SwashplateImage->setSceneRect(-50,-30,500,500);
|
m_ccpm->SwashplateImage->setSceneRect(-50,-30,500,500);
|
||||||
//m_ccpm->SwashplateImage->scale(.85,.85);
|
//m_ccpm->SwashplateImage->scale(.85,.85);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QSvgRenderer *renderer = new QSvgRenderer();
|
QSvgRenderer *renderer = new QSvgRenderer();
|
||||||
renderer->load(QString(":/configgadget/images/ccpm_setup.svg"));
|
renderer->load(QString(":/configgadget/images/ccpm_setup.svg"));
|
||||||
|
|
||||||
@ -132,78 +131,25 @@ ConfigccpmWidget::ConfigccpmWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|||||||
|
|
||||||
SwashLvlSpinBoxes[i] = new QSpinBox(m_ccpm->SwashLvlSwashplateImage); // use QGraphicsView
|
SwashLvlSpinBoxes[i] = new QSpinBox(m_ccpm->SwashLvlSwashplateImage); // use QGraphicsView
|
||||||
m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
|
m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
|
||||||
//SwashLvlSpinBoxes[i]->move(i*50+50,20);
|
|
||||||
//SwashLvlSpinBoxes[i]->resize(40,20);
|
|
||||||
//SwashLvlSpinBoxes[i]->heightForWidth()
|
|
||||||
SwashLvlSpinBoxes[i]->setFixedSize(50,20);
|
|
||||||
SwashLvlSpinBoxes[i]->setMaximum(10000);
|
SwashLvlSpinBoxes[i]->setMaximum(10000);
|
||||||
SwashLvlSpinBoxes[i]->setMinimum(0);
|
SwashLvlSpinBoxes[i]->setMinimum(0);
|
||||||
SwashLvlSpinBoxes[i]->setValue(0);
|
SwashLvlSpinBoxes[i]->setValue(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Servos[0] = new QGraphicsSvgItem();
|
|
||||||
Servos[0]->setSharedRenderer(renderer);
|
|
||||||
Servos[0]->setElementId("ServoW");
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(Servos[0]);
|
|
||||||
|
|
||||||
Servos[1] = new QGraphicsSvgItem();
|
|
||||||
Servos[1]->setSharedRenderer(renderer);
|
|
||||||
Servos[1]->setElementId("ServoX");
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(Servos[1]);
|
|
||||||
|
|
||||||
Servos[2] = new QGraphicsSvgItem();
|
|
||||||
Servos[2]->setSharedRenderer(renderer);
|
|
||||||
Servos[2]->setElementId("ServoY");
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(Servos[2]);
|
|
||||||
|
|
||||||
Servos[3] = new QGraphicsSvgItem();
|
|
||||||
Servos[3]->setSharedRenderer(renderer);
|
|
||||||
Servos[3]->setElementId("ServoZ");
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(Servos[3]);
|
|
||||||
|
|
||||||
|
|
||||||
ServosText[0] = new QGraphicsTextItem();
|
|
||||||
ServosText[0]->setDefaultTextColor(Qt::red);
|
|
||||||
ServosText[0]->setPlainText(QString("-"));
|
|
||||||
ServosText[0]->setFont(serifFont);
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(ServosText[0]);
|
|
||||||
|
|
||||||
ServosText[1] = new QGraphicsTextItem();
|
|
||||||
ServosText[1]->setDefaultTextColor(Qt::red);
|
|
||||||
ServosText[1]->setPlainText(QString("-"));
|
|
||||||
ServosText[1]->setFont(serifFont);
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(ServosText[1]);
|
|
||||||
|
|
||||||
ServosText[2] = new QGraphicsTextItem();
|
|
||||||
ServosText[2]->setDefaultTextColor(Qt::red);
|
|
||||||
ServosText[2]->setPlainText(QString("-"));
|
|
||||||
ServosText[2]->setFont(serifFont);
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(ServosText[2]);
|
|
||||||
|
|
||||||
ServosText[3] = new QGraphicsTextItem();
|
|
||||||
ServosText[3]->setDefaultTextColor(Qt::red);
|
|
||||||
ServosText[3]->setPlainText(QString("-"));
|
|
||||||
ServosText[3]->setFont(serifFont);
|
|
||||||
m_ccpm->SwashplateImage->scene()->addItem(ServosText[3]);
|
|
||||||
*/
|
|
||||||
m_ccpm->PitchCurve->setMin(-1);
|
m_ccpm->PitchCurve->setMin(-1);
|
||||||
|
|
||||||
resetMixer(m_ccpm->PitchCurve, 5);
|
resetMixer(m_ccpm->PitchCurve, 5);
|
||||||
resetMixer(m_ccpm->ThrottleCurve, 5);
|
resetMixer(m_ccpm->ThrottleCurve, 5);
|
||||||
|
|
||||||
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(mixerSettings);
|
||||||
|
UAVObjectField * curve2source = mixerSettings->getField("Curve2Source");
|
||||||
|
Q_ASSERT(curve2source);
|
||||||
|
|
||||||
QStringList channels;
|
QStringList channels;
|
||||||
channels << "Channel1" << "Channel2" <<
|
channels << "Channel1" << "Channel2" << "Channel3" << "Channel4" <<
|
||||||
"Channel3" << "Channel4" << "Channel5" << "Channel6" << "Channel7" << "Channel8" ;
|
"Channel5" << "Channel6" << "Channel7" << "Channel8" << "None";
|
||||||
m_ccpm->ccpmCollectiveChannel->addItems(channels);
|
|
||||||
m_ccpm->ccpmCollectiveChannel->setCurrentIndex(8);
|
|
||||||
channels << "None" ;
|
|
||||||
m_ccpm->ccpmEngineChannel->addItems(channels);
|
m_ccpm->ccpmEngineChannel->addItems(channels);
|
||||||
m_ccpm->ccpmEngineChannel->setCurrentIndex(8);
|
m_ccpm->ccpmEngineChannel->setCurrentIndex(8);
|
||||||
m_ccpm->ccpmTailChannel->addItems(channels);
|
m_ccpm->ccpmTailChannel->addItems(channels);
|
||||||
@ -218,17 +164,17 @@ ConfigccpmWidget::ConfigccpmWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|||||||
m_ccpm->ccpmServoZChannel->setCurrentIndex(8);
|
m_ccpm->ccpmServoZChannel->setCurrentIndex(8);
|
||||||
|
|
||||||
QStringList Types;
|
QStringList Types;
|
||||||
Types << "CCPM 2 Servo 90º" << "CCPM 3 Servo 90º" << "CCPM 4 Servo 90º" << "CCPM 3 Servo 120º" << "CCPM 3 Servo 140º" << "FP 2 Servo 90º" << "Custom - User Angles" << "Custom - Advanced Settings" ;
|
Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º") <<
|
||||||
|
QString::fromUtf8("CCPM 4 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 120º") <<
|
||||||
|
QString::fromUtf8("CCPM 3 Servo 140º") << QString::fromUtf8("FP 2 Servo 90º") <<
|
||||||
|
QString::fromUtf8("Custom - User Angles") << QString::fromUtf8("Custom - Advanced Settings");
|
||||||
m_ccpm->ccpmType->addItems(Types);
|
m_ccpm->ccpmType->addItems(Types);
|
||||||
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - 1);
|
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - 1);
|
||||||
requestccpmUpdate();
|
requestccpmUpdate();
|
||||||
UpdateCurveSettings();
|
UpdateCurveSettings();
|
||||||
|
|
||||||
|
|
||||||
//disable changing number of points in curves until UAVObjects have more than 5
|
//disable changing number of points in curves until UAVObjects have more than 5
|
||||||
m_ccpm->NumCurvePoints->setEnabled(0);
|
m_ccpm->NumCurvePoints->setEnabled(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UpdateType();
|
UpdateType();
|
||||||
|
|
||||||
@ -270,15 +216,12 @@ ConfigccpmWidget::ConfigccpmWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|||||||
connect(m_ccpm->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed()));
|
connect(m_ccpm->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed()));
|
||||||
connect(m_ccpm->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed()));
|
connect(m_ccpm->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed()));
|
||||||
|
|
||||||
connect(m_ccpm->ccpmCollectivePassthrough, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
|
||||||
connect(m_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
connect(m_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
||||||
connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ccpmSwashplateRedraw();
|
ccpmSwashplateRedraw();
|
||||||
// connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestccpmUpdate()));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigccpmWidget::~ConfigccpmWidget()
|
ConfigccpmWidget::~ConfigccpmWidget()
|
||||||
@ -292,7 +235,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
QString TypeText;
|
QString TypeText;
|
||||||
double AdjustmentAngle=0;
|
double AdjustmentAngle=0;
|
||||||
|
|
||||||
UpdatCCPMOptionsFromUI();
|
UpdateCCPMOptionsFromUI();
|
||||||
SetUIComponentVisibilities();
|
SetUIComponentVisibilities();
|
||||||
|
|
||||||
TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
|
TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
|
||||||
@ -332,7 +275,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
|
|
||||||
NumServosDefined=4;
|
NumServosDefined=4;
|
||||||
//set values for pre defined heli types
|
//set values for pre defined heli types
|
||||||
if (TypeText.compare(QString("CCPM 2 Servo 90º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("CCPM 2 Servo 90º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
||||||
@ -348,7 +291,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
NumServosDefined=2;
|
NumServosDefined=2;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TypeText.compare(QString("CCPM 3 Servo 90º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 90º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
||||||
@ -361,7 +304,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
NumServosDefined=3;
|
NumServosDefined=3;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TypeText.compare(QString("CCPM 4 Servo 90º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("CCPM 4 Servo 90º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
||||||
@ -373,7 +316,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
NumServosDefined=4;
|
NumServosDefined=4;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TypeText.compare(QString("CCPM 3 Servo 120º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 120º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 120,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 120,360));
|
||||||
@ -386,7 +329,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
NumServosDefined=3;
|
NumServosDefined=3;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TypeText.compare(QString("CCPM 3 Servo 140º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 140º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 140,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 140,360));
|
||||||
@ -399,7 +342,7 @@ void ConfigccpmWidget::UpdateType()
|
|||||||
NumServosDefined=3;
|
NumServosDefined=3;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TypeText.compare(QString("FP 2 Servo 90º"), Qt::CaseInsensitive)==0)
|
if (TypeText.compare(QString::fromUtf8("FP 2 Servo 90º"), Qt::CaseInsensitive)==0)
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
|
||||||
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
|
||||||
@ -505,6 +448,9 @@ void ConfigccpmWidget::UpdateCurveWidgets()
|
|||||||
|
|
||||||
void ConfigccpmWidget::updatePitchCurveValue(QList<double> curveValues0,double Value0)
|
void ConfigccpmWidget::updatePitchCurveValue(QList<double> curveValues0,double Value0)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(curveValues0);
|
||||||
|
Q_UNUSED(Value0);
|
||||||
|
|
||||||
int NumCurvePoints,i;
|
int NumCurvePoints,i;
|
||||||
double CurrentValue;
|
double CurrentValue;
|
||||||
QList<double> internalCurveValues;
|
QList<double> internalCurveValues;
|
||||||
@ -526,6 +472,9 @@ void ConfigccpmWidget::updatePitchCurveValue(QList<double> curveValues0,double V
|
|||||||
|
|
||||||
void ConfigccpmWidget::updateThrottleCurveValue(QList<double> curveValues0,double Value0)
|
void ConfigccpmWidget::updateThrottleCurveValue(QList<double> curveValues0,double Value0)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(curveValues0);
|
||||||
|
Q_UNUSED(Value0);
|
||||||
|
|
||||||
int NumCurvePoints,i;
|
int NumCurvePoints,i;
|
||||||
double CurrentValue;
|
double CurrentValue;
|
||||||
QList<double> internalCurveValues;
|
QList<double> internalCurveValues;
|
||||||
@ -915,14 +864,10 @@ void ConfigccpmWidget::UpdateMixer()
|
|||||||
bool useCyclic;
|
bool useCyclic;
|
||||||
int i,j,ThisEnable[6];
|
int i,j,ThisEnable[6];
|
||||||
float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6];
|
float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6];
|
||||||
//QTableWidgetItem *newItem;// = new QTableWidgetItem();
|
|
||||||
QString Channel;
|
QString Channel;
|
||||||
|
|
||||||
ccpmChannelCheck();
|
ccpmChannelCheck();
|
||||||
//Type = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
|
UpdateCCPMOptionsFromUI();
|
||||||
//CollectiveConstant=m_ccpm->ccpmCollectiveSlider->value()/100.0;
|
|
||||||
//CorrectionAngle=m_ccpm->ccpmCorrectionAngle->value();
|
|
||||||
UpdatCCPMOptionsFromUI();
|
|
||||||
|
|
||||||
useCCPM = !(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
useCCPM = !(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
useCyclic = GUIConfigData.heli.ccpmLinkRollState;
|
useCyclic = GUIConfigData.heli.ccpmLinkRollState;
|
||||||
@ -978,15 +923,6 @@ void ConfigccpmWidget::UpdateMixer()
|
|||||||
//go through the user data and update the mixer matrix
|
//go through the user data and update the mixer matrix
|
||||||
for (i=0;i<6;i++)
|
for (i=0;i<6;i++)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
data.Mixer0Type = 0;//Disabled,Motor,Servo
|
|
||||||
data.Mixer0Vector[0] = 0;//ThrottleCurve1
|
|
||||||
data.Mixer0Vector[1] = 0;//ThrottleCurve2
|
|
||||||
data.Mixer0Vector[2] = 0;//Roll
|
|
||||||
data.Mixer0Vector[3] = 0;//Pitch
|
|
||||||
data.Mixer0Vector[4] = 0;//Yaw
|
|
||||||
|
|
||||||
*/
|
|
||||||
if ((MixerChannelData[i]<8)&&((ThisEnable[i])||(i<2)))
|
if ((MixerChannelData[i]<8)&&((ThisEnable[i])||(i<2)))
|
||||||
{
|
{
|
||||||
m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->setText(QString("%1").arg( MixerChannelData[i]+1 ));
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->setText(QString("%1").arg( MixerChannelData[i]+1 ));
|
||||||
@ -1055,7 +991,7 @@ void ConfigccpmWidget::UpdateMixer()
|
|||||||
} __attribute__((packed)) heliGUISettingsStruct;
|
} __attribute__((packed)) heliGUISettingsStruct;
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void ConfigccpmWidget::UpdatCCPMOptionsFromUI()
|
void ConfigccpmWidget::UpdateCCPMOptionsFromUI()
|
||||||
{
|
{
|
||||||
bool useCCPM;
|
bool useCCPM;
|
||||||
bool useCyclic;
|
bool useCyclic;
|
||||||
@ -1076,9 +1012,6 @@ void ConfigccpmWidget::UpdatCCPMOptionsFromUI()
|
|||||||
//correction angle
|
//correction angle
|
||||||
GUIConfigData.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
|
GUIConfigData.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
|
||||||
|
|
||||||
//CollectiveChannel
|
|
||||||
GUIConfigData.heli.CollectiveChannel = m_ccpm->ccpmCollectiveChannel->currentIndex();
|
|
||||||
|
|
||||||
//update sliders
|
//update sliders
|
||||||
if (useCCPM)
|
if (useCCPM)
|
||||||
{
|
{
|
||||||
@ -1097,7 +1030,6 @@ void ConfigccpmWidget::UpdatCCPMOptionsFromUI()
|
|||||||
GUIConfigData.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
|
GUIConfigData.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
|
||||||
}
|
}
|
||||||
GUIConfigData.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
|
GUIConfigData.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
|
||||||
//GUIConfigData.heli.RevoSlider = m_ccpm->ccpmREVOScale->value();
|
|
||||||
|
|
||||||
//servo assignments
|
//servo assignments
|
||||||
GUIConfigData.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex();
|
GUIConfigData.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex();
|
||||||
@ -1106,7 +1038,7 @@ void ConfigccpmWidget::UpdatCCPMOptionsFromUI()
|
|||||||
GUIConfigData.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex();
|
GUIConfigData.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex();
|
||||||
|
|
||||||
}
|
}
|
||||||
void ConfigccpmWidget::UpdatCCPMUIFromOptions()
|
void ConfigccpmWidget::UpdateCCPMUIFromOptions()
|
||||||
{
|
{
|
||||||
//swashplate config
|
//swashplate config
|
||||||
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - (GUIConfigData.heli.SwasplateType +1));
|
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - (GUIConfigData.heli.SwasplateType +1));
|
||||||
@ -1119,10 +1051,7 @@ void ConfigccpmWidget::UpdatCCPMUIFromOptions()
|
|||||||
|
|
||||||
//correction angle
|
//correction angle
|
||||||
m_ccpm->ccpmCorrectionAngle->setValue(GUIConfigData.heli.CorrectionAngle);
|
m_ccpm->ccpmCorrectionAngle->setValue(GUIConfigData.heli.CorrectionAngle);
|
||||||
|
|
||||||
//CollectiveChannel
|
|
||||||
m_ccpm->ccpmCollectiveChannel->setCurrentIndex(GUIConfigData.heli.CollectiveChannel);
|
|
||||||
|
|
||||||
//update sliders
|
//update sliders
|
||||||
m_ccpm->ccpmCollectiveScale->setValue(GUIConfigData.heli.SliderValue0);
|
m_ccpm->ccpmCollectiveScale->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
m_ccpm->ccpmCollectiveScaleBox->setValue(GUIConfigData.heli.SliderValue0);
|
m_ccpm->ccpmCollectiveScaleBox->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
@ -1134,7 +1063,6 @@ void ConfigccpmWidget::UpdatCCPMUIFromOptions()
|
|||||||
m_ccpm->ccpmRollScaleBox->setValue(GUIConfigData.heli.SliderValue2);
|
m_ccpm->ccpmRollScaleBox->setValue(GUIConfigData.heli.SliderValue2);
|
||||||
m_ccpm->ccpmCollectiveSlider->setValue(GUIConfigData.heli.SliderValue0);
|
m_ccpm->ccpmCollectiveSlider->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
m_ccpm->ccpmCollectivespinBox->setValue(GUIConfigData.heli.SliderValue0);
|
m_ccpm->ccpmCollectivespinBox->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
//m_ccpm->ccpmREVOScale->setValue(GUIConfigData.heli.RevoSlider);
|
|
||||||
|
|
||||||
//servo assignments
|
//servo assignments
|
||||||
m_ccpm->ccpmServoWChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexW);
|
m_ccpm->ccpmServoWChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexW);
|
||||||
@ -1147,16 +1075,13 @@ void ConfigccpmWidget::UpdatCCPMUIFromOptions()
|
|||||||
|
|
||||||
void ConfigccpmWidget::SetUIComponentVisibilities()
|
void ConfigccpmWidget::SetUIComponentVisibilities()
|
||||||
{
|
{
|
||||||
UpdatCCPMOptionsFromUI();
|
UpdateCCPMOptionsFromUI();
|
||||||
//set which sliders are user...
|
//set which sliders are user...
|
||||||
m_ccpm->ccpmRevoMixingBox->setVisible(0);
|
m_ccpm->ccpmRevoMixingBox->setVisible(0);
|
||||||
|
|
||||||
m_ccpm->ccpmPitchMixingBox->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState && GUIConfigData.heli.ccpmLinkCyclicState);
|
m_ccpm->ccpmPitchMixingBox->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState && GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
m_ccpm->ccpmCollectiveScalingBox->setVisible(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
m_ccpm->ccpmCollectiveScalingBox->setVisible(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
|
||||||
m_ccpm->ccpmCollectiveChLabel->setVisible(GUIConfigData.heli.ccpmCollectivePassthroughState);
|
|
||||||
m_ccpm->ccpmCollectiveChannel->setVisible(GUIConfigData.heli.ccpmCollectivePassthroughState);
|
|
||||||
|
|
||||||
m_ccpm->ccpmLinkCyclic->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState);
|
m_ccpm->ccpmLinkCyclic->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState);
|
||||||
|
|
||||||
m_ccpm->ccpmCyclicScalingBox->setVisible((GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState) && GUIConfigData.heli.ccpmLinkRollState);
|
m_ccpm->ccpmCyclicScalingBox->setVisible((GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState) && GUIConfigData.heli.ccpmLinkRollState);
|
||||||
@ -1183,20 +1108,17 @@ void ConfigccpmWidget::requestccpmUpdate()
|
|||||||
#define MaxAngleError 2
|
#define MaxAngleError 2
|
||||||
int MixerDataFromHeli[8][5];
|
int MixerDataFromHeli[8][5];
|
||||||
quint8 MixerOutputType[8];
|
quint8 MixerOutputType[8];
|
||||||
int EngineChannel,TailRotorChannel,ServoChannels[4],ServoAngles[4],SortAngles[4],CalcAngles[4],ServoCurve2[4];
|
int EngineChannel,TailRotorChannel,ServoChannels[4],ServoAngles[4],SortAngles[4],ServoCurve2[4];
|
||||||
int NumServos=0;
|
int NumServos=0;
|
||||||
double Collective=0.0;
|
|
||||||
double a1,a2;
|
|
||||||
int HeadRotation,temp;
|
|
||||||
int isCCPM=0;
|
|
||||||
|
|
||||||
if (SwashLvlConfigurationInProgress)return;
|
if (SwashLvlConfigurationInProgress)return;
|
||||||
if (updatingToHardware)return;
|
if (updatingToHardware)return;
|
||||||
updatingFromHardware=TRUE;
|
updatingFromHardware=TRUE;
|
||||||
|
|
||||||
int i,j;
|
unsigned int i,j;
|
||||||
|
|
||||||
SystemSettings * systemSettings = SystemSettings::GetInstance(getObjectManager());
|
SystemSettings * systemSettings = SystemSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(systemSettings);
|
||||||
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
|
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
|
||||||
|
|
||||||
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM ==
|
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM ==
|
||||||
@ -1205,7 +1127,7 @@ void ConfigccpmWidget::requestccpmUpdate()
|
|||||||
for(i = 0; i < SystemSettings::GUICONFIGDATA_NUMELEM; i++)
|
for(i = 0; i < SystemSettings::GUICONFIGDATA_NUMELEM; i++)
|
||||||
GUIConfigData.UAVObject[i]=systemSettingsData.GUIConfigData[i];
|
GUIConfigData.UAVObject[i]=systemSettingsData.GUIConfigData[i];
|
||||||
|
|
||||||
UpdatCCPMUIFromOptions();
|
UpdateCCPMUIFromOptions();
|
||||||
|
|
||||||
// Get existing mixer settings
|
// Get existing mixer settings
|
||||||
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
@ -1299,7 +1221,7 @@ void ConfigccpmWidget::requestccpmUpdate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
updatingFromHardware=FALSE;
|
updatingFromHardware=FALSE;
|
||||||
UpdatCCPMUIFromOptions();
|
UpdateCCPMUIFromOptions();
|
||||||
ccpmSwashplateUpdate();
|
ccpmSwashplateUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1310,116 +1232,83 @@ void ConfigccpmWidget::requestccpmUpdate()
|
|||||||
void ConfigccpmWidget::sendccpmUpdate()
|
void ConfigccpmWidget::sendccpmUpdate()
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
UAVObjectField *field;
|
|
||||||
UAVDataObject* obj;
|
|
||||||
|
|
||||||
if (SwashLvlConfigurationInProgress)return;
|
if (SwashLvlConfigurationInProgress)return;
|
||||||
updatingToHardware=TRUE;
|
updatingToHardware=TRUE;
|
||||||
//ShowDisclaimer(1);
|
//ShowDisclaimer(1);
|
||||||
|
|
||||||
|
UpdateCCPMOptionsFromUI();
|
||||||
|
|
||||||
|
// Store the data required to reconstruct
|
||||||
|
SystemSettings * systemSettings = SystemSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(systemSettings);
|
||||||
|
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
|
||||||
|
systemSettingsData.GUIConfigData[0] = GUIConfigData.UAVObject[0];
|
||||||
|
systemSettingsData.GUIConfigData[1] = GUIConfigData.UAVObject[1];
|
||||||
|
systemSettings->setData(systemSettingsData);
|
||||||
|
systemSettings->updated();
|
||||||
|
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
Q_ASSERT(mixerSettings);
|
||||||
|
MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
|
||||||
|
|
||||||
UpdatCCPMOptionsFromUI();
|
UpdateMixer();
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
|
||||||
field = obj->getField(QString("GUIConfigData"));
|
|
||||||
field->setValue(GUIConfigData.UAVObject[0],0);
|
|
||||||
field->setValue(GUIConfigData.UAVObject[1],1);
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set up some helper pointers
|
||||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("MixerSettings")));
|
qint8 * mixers[8] = {mixerSettingsData.Mixer1Vector,
|
||||||
Q_ASSERT(obj);
|
mixerSettingsData.Mixer2Vector,
|
||||||
|
mixerSettingsData.Mixer3Vector,
|
||||||
|
mixerSettingsData.Mixer4Vector,
|
||||||
|
mixerSettingsData.Mixer5Vector,
|
||||||
|
mixerSettingsData.Mixer6Vector,
|
||||||
|
mixerSettingsData.Mixer7Vector,
|
||||||
|
mixerSettingsData.Mixer8Vector
|
||||||
|
};
|
||||||
|
|
||||||
UpdateMixer();
|
quint8 * mixerTypes[8] = {
|
||||||
|
&mixerSettingsData.Mixer1Type,
|
||||||
|
&mixerSettingsData.Mixer2Type,
|
||||||
|
&mixerSettingsData.Mixer3Type,
|
||||||
|
&mixerSettingsData.Mixer4Type,
|
||||||
|
&mixerSettingsData.Mixer5Type,
|
||||||
|
&mixerSettingsData.Mixer6Type,
|
||||||
|
&mixerSettingsData.Mixer7Type,
|
||||||
|
&mixerSettingsData.Mixer8Type
|
||||||
|
};
|
||||||
|
|
||||||
//clear the output types
|
//go through the user data and update the mixer matrix
|
||||||
for (i=0;i<8;i++)
|
for (i=0;i<6;i++)
|
||||||
|
{
|
||||||
|
if (MixerChannelData[i]<8)
|
||||||
{
|
{
|
||||||
field = obj->getField( QString( "Mixer%1Type" ).arg( i+1 ));
|
//set the mixer type
|
||||||
//clear the mixer type
|
*(mixerTypes[MixerChannelData[i]]) = i==0 ?
|
||||||
field->setValue("Disabled");
|
MixerSettings::MIXER1TYPE_MOTOR :
|
||||||
|
MixerSettings::MIXER1TYPE_SERVO;
|
||||||
|
|
||||||
|
//config the vector
|
||||||
|
for (j=0;j<5;j++)
|
||||||
|
mixers[MixerChannelData[i]][j] = m_ccpm->ccpmAdvancedSettingsTable->item(i,j+1)->text().toInt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the user data for the curve into the mixer settings
|
||||||
|
for (i=0;i<5;i++)
|
||||||
|
mixerSettingsData.ThrottleCurve1[i] = m_ccpm->CurveSettings->item(i, 0)->text().toDouble();
|
||||||
|
|
||||||
//go through the user data and update the mixer matrix
|
for (i=0;i<5;i++)
|
||||||
for (i=0;i<6;i++)
|
mixerSettingsData.ThrottleCurve2[i] = m_ccpm->CurveSettings->item(i, 1)->text().toDouble();
|
||||||
{
|
|
||||||
/*
|
|
||||||
data.Mixer0Type = 0;//Disabled,Motor,Servo
|
|
||||||
data.Mixer0Vector[0] = 0;//ThrottleCurve1
|
|
||||||
data.Mixer0Vector[1] = 0;//ThrottleCurve2
|
|
||||||
data.Mixer0Vector[2] = 0;//Roll
|
|
||||||
data.Mixer0Vector[3] = 0;//Pitch
|
|
||||||
data.Mixer0Vector[4] = 0;//Yaw
|
|
||||||
|
|
||||||
*/
|
|
||||||
if (MixerChannelData[i]<8)
|
|
||||||
{
|
|
||||||
//select the correct mixer for this config element
|
|
||||||
field = obj->getField(QString( "Mixer%1Type" ).arg( MixerChannelData[i]+1 ));
|
|
||||||
//set the mixer type
|
|
||||||
if (i==0)
|
|
||||||
{
|
|
||||||
field->setValue("Motor");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
field->setValue("Servo");
|
|
||||||
}
|
|
||||||
|
|
||||||
//select the correct mixer for this config element
|
|
||||||
field = obj->getField(QString( "Mixer%1Vector" ).arg( MixerChannelData[i]+1 ));
|
|
||||||
//config the vector
|
|
||||||
for (j=0;j<5;j++)
|
|
||||||
{
|
|
||||||
field->setValue(m_ccpm->ccpmAdvancedSettingsTable->item(i,j+1)->text().toInt(),j);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//get the user data for the curve into the mixer settings
|
|
||||||
field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
for (i=0;i<5;i++)
|
|
||||||
{
|
|
||||||
field->setValue(m_ccpm->CurveSettings->item(i, 0)->text().toDouble(),i);
|
|
||||||
}
|
|
||||||
field = obj->getField(QString("ThrottleCurve2"));
|
|
||||||
for (i=0;i<5;i++)
|
|
||||||
{
|
|
||||||
field->setValue(m_ccpm->CurveSettings->item(i, 1)->text().toDouble(),i);
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
field = obj->getField(QString("Curve2Source"));
|
|
||||||
|
|
||||||
//mapping of collective input to curve 2...
|
//mapping of collective input to curve 2...
|
||||||
//MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5
|
//MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5
|
||||||
//check if we are using throttle or directly from a channel...
|
//check if we are using throttle or directly from a channel...
|
||||||
if (GUIConfigData.heli.ccpmCollectivePassthroughState)
|
if (GUIConfigData.heli.ccpmCollectivePassthroughState)
|
||||||
{// input channel
|
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_COLLECTIVE;
|
||||||
field->setValue("Accessory0");
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
field = obj->getField(QString("Accessory0"));
|
|
||||||
field->setValue(tr( "Channel%1" ).arg(GUIConfigData.heli.CollectiveChannel+1));
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{// throttle
|
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE;
|
||||||
|
|
||||||
field->setValue("Throttle");
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->updated();
|
mixerSettings->setData(mixerSettingsData);
|
||||||
|
mixerSettings->updated();
|
||||||
updatingToHardware=FALSE;
|
updatingToHardware=FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1820,7 +1709,6 @@ void ConfigccpmWidget::enableSwashplateLevellingControl(bool state)
|
|||||||
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
mdata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||||
mdata.gcsTelemetryUpdatePeriod = 100;
|
mdata.gcsTelemetryUpdatePeriod = 100;
|
||||||
SwashLvlConfigurationInProgress=1;
|
SwashLvlConfigurationInProgress=1;
|
||||||
connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),this, SLOT(FocusChanged(QWidget*,QWidget*)));
|
|
||||||
m_ccpm->TabObject->setTabEnabled(0,0);
|
m_ccpm->TabObject->setTabEnabled(0,0);
|
||||||
m_ccpm->TabObject->setTabEnabled(2,0);
|
m_ccpm->TabObject->setTabEnabled(2,0);
|
||||||
m_ccpm->TabObject->setTabEnabled(3,0);
|
m_ccpm->TabObject->setTabEnabled(3,0);
|
||||||
@ -1831,7 +1719,6 @@ void ConfigccpmWidget::enableSwashplateLevellingControl(bool state)
|
|||||||
mdata = SwashLvlaccInitialData; // Restore metadata
|
mdata = SwashLvlaccInitialData; // Restore metadata
|
||||||
SwashLvlConfigurationInProgress=0;
|
SwashLvlConfigurationInProgress=0;
|
||||||
|
|
||||||
disconnect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),this, SLOT(FocusChanged(QWidget*,QWidget*)));
|
|
||||||
m_ccpm->TabObject->setTabEnabled(0,1);
|
m_ccpm->TabObject->setTabEnabled(0,1);
|
||||||
m_ccpm->TabObject->setTabEnabled(2,1);
|
m_ccpm->TabObject->setTabEnabled(2,1);
|
||||||
m_ccpm->TabObject->setTabEnabled(3,1);
|
m_ccpm->TabObject->setTabEnabled(3,1);
|
||||||
@ -1857,41 +1744,24 @@ void ConfigccpmWidget::setSwashplateLevel(int percent)
|
|||||||
|
|
||||||
SwashLvlServoInterlock=1;
|
SwashLvlServoInterlock=1;
|
||||||
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
|
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
|
||||||
UAVObjectField * channel = obj->getField("Channel");
|
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
|
||||||
|
|
||||||
|
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) {
|
||||||
|
if (level==0)
|
||||||
if (level==0)
|
value = newSwashLvlConfiguration.Neutral[i];
|
||||||
{
|
else if (level > 0)
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
{
|
|
||||||
channel->setValue(newSwashLvlConfiguration.Neutral[i],newSwashLvlConfiguration.ServoChannels[i]);
|
|
||||||
SwashLvlSpinBoxes[i]->setValue(newSwashLvlConfiguration.Neutral[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (level>0)
|
|
||||||
{
|
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
{
|
|
||||||
value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i])*level + newSwashLvlConfiguration.Neutral[i];
|
value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i])*level + newSwashLvlConfiguration.Neutral[i];
|
||||||
channel->setValue(value,newSwashLvlConfiguration.ServoChannels[i]);
|
else if (level < 0)
|
||||||
SwashLvlSpinBoxes[i]->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (level<0)
|
|
||||||
{
|
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
{
|
|
||||||
value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i])*level + newSwashLvlConfiguration.Neutral[i];
|
value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i])*level + newSwashLvlConfiguration.Neutral[i];
|
||||||
channel->setValue(value,newSwashLvlConfiguration.ServoChannels[i]);
|
|
||||||
SwashLvlSpinBoxes[i]->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
|
||||||
|
SwashLvlSpinBoxes[i]->setValue(value);
|
||||||
}
|
}
|
||||||
obj->updated();
|
|
||||||
|
actuatorCommand->setData(actuatorCommandData);
|
||||||
|
actuatorCommand->updated();
|
||||||
|
|
||||||
SwashLvlServoInterlock=0;
|
SwashLvlServoInterlock=0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1900,76 +1770,41 @@ return;
|
|||||||
|
|
||||||
void ConfigccpmWidget::SwashLvlSpinBoxChanged(int value)
|
void ConfigccpmWidget::SwashLvlSpinBoxChanged(int value)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(value);
|
||||||
int i;
|
int i;
|
||||||
if (SwashLvlServoInterlock==1)return;
|
if (SwashLvlServoInterlock==1)return;
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
|
|
||||||
UAVObjectField * channel = obj->getField("Channel");
|
|
||||||
|
|
||||||
switch (SwashLvlState)
|
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
|
||||||
{
|
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
|
||||||
case 0:
|
|
||||||
break;
|
for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
|
||||||
case 1: //Neutral levelling
|
value = SwashLvlSpinBoxes[i]->value();
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
|
switch (SwashLvlState)
|
||||||
{
|
{
|
||||||
newSwashLvlConfiguration.Neutral[i]=SwashLvlSpinBoxes[i]->value();
|
case 1: //Neutral levelling
|
||||||
channel->setValue(newSwashLvlConfiguration.Neutral[i],newSwashLvlConfiguration.ServoChannels[i]);
|
newSwashLvlConfiguration.Neutral[i]=value;
|
||||||
|
break;
|
||||||
|
case 2: //Max levelling
|
||||||
|
newSwashLvlConfiguration.Max[i] = value;
|
||||||
|
break;
|
||||||
|
case 3: //Min levelling
|
||||||
|
newSwashLvlConfiguration.Min[i]= value;
|
||||||
|
break;
|
||||||
|
case 4: //levelling verification
|
||||||
|
break;
|
||||||
|
case 5: //levelling complete
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
obj->updated();
|
|
||||||
break;
|
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
|
||||||
case 2: //Max levelling
|
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
{
|
|
||||||
newSwashLvlConfiguration.Max[i]=SwashLvlSpinBoxes[i]->value();
|
|
||||||
channel->setValue(newSwashLvlConfiguration.Max[i],newSwashLvlConfiguration.ServoChannels[i]);
|
|
||||||
}
|
|
||||||
obj->updated();
|
|
||||||
break;
|
|
||||||
case 3: //Min levelling
|
|
||||||
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
|
||||||
{
|
|
||||||
newSwashLvlConfiguration.Min[i]=SwashLvlSpinBoxes[i]->value();
|
|
||||||
channel->setValue(newSwashLvlConfiguration.Min[i],newSwashLvlConfiguration.ServoChannels[i]);
|
|
||||||
}
|
|
||||||
obj->updated();
|
|
||||||
break;
|
|
||||||
case 4: //levelling verification
|
|
||||||
break;
|
|
||||||
case 5: //levelling complete
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
actuatorCommand->setData(actuatorCommandData);
|
||||||
|
actuatorCommand->updated();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConfigccpmWidget::FocusChanged(QWidget *oldFocus, QWidget *newFocus)
|
|
||||||
{
|
|
||||||
if (SwashLvlConfigurationInProgress!=1) return;
|
|
||||||
QMessageBox msgBox;
|
|
||||||
int ret;
|
|
||||||
msgBox.setText("<h1>Warning!!!</h1>");
|
|
||||||
|
|
||||||
if ((this->isAncestorOf(oldFocus))&&(!this->isAncestorOf(newFocus)))
|
|
||||||
{
|
|
||||||
msgBox.setInformativeText("<b>You are in the middle of the levelling routine</b><br>Changing focus will cancel all levelling and return the OP hardware to the state it was in before levelling began.<p>Do you want to continue the levelling routine?");
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::Yes);
|
|
||||||
msgBox.setIcon(QMessageBox::Information);
|
|
||||||
ret = msgBox.exec();
|
|
||||||
|
|
||||||
if (ret == QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
|
|
||||||
//m_ccpm->TabObject->setCurrentIndex(1);
|
|
||||||
//m_ccpm->SwashPlateLevel->setFocus(Qt::MouseFocusReason);
|
|
||||||
//m_ccpm->SwashLvlInstructionsBox->setFocus(Qt::MouseFocusReason);
|
|
||||||
oldFocus->setFocus(Qt::MouseFocusReason);
|
|
||||||
}
|
|
||||||
if (ret == QMessageBox::No)
|
|
||||||
{
|
|
||||||
SwashLvlCancelButtonPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -57,7 +57,6 @@ typedef struct {
|
|||||||
uint ccpmCollectivePassthroughState:1;
|
uint ccpmCollectivePassthroughState:1;
|
||||||
uint ccpmLinkCyclicState:1;
|
uint ccpmLinkCyclicState:1;
|
||||||
uint ccpmLinkRollState:1;
|
uint ccpmLinkRollState:1;
|
||||||
uint CollectiveChannel:3;//20bits
|
|
||||||
uint SliderValue0:7;
|
uint SliderValue0:7;
|
||||||
uint SliderValue1:7;
|
uint SliderValue1:7;
|
||||||
uint SliderValue2:7;//41bits
|
uint SliderValue2:7;//41bits
|
||||||
@ -82,6 +81,8 @@ public:
|
|||||||
ConfigccpmWidget(QWidget *parent = 0);
|
ConfigccpmWidget(QWidget *parent = 0);
|
||||||
~ConfigccpmWidget();
|
~ConfigccpmWidget();
|
||||||
|
|
||||||
|
friend class ConfigAirframeWidget;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_ccpmWidget *m_ccpm;
|
Ui_ccpmWidget *m_ccpm;
|
||||||
QGraphicsSvgItem *SwashplateImg;
|
QGraphicsSvgItem *SwashplateImg;
|
||||||
@ -134,8 +135,8 @@ private:
|
|||||||
void SwashLvlCancelButtonPressed();
|
void SwashLvlCancelButtonPressed();
|
||||||
void SwashLvlFinishButtonPressed();
|
void SwashLvlFinishButtonPressed();
|
||||||
|
|
||||||
void UpdatCCPMOptionsFromUI();
|
void UpdateCCPMOptionsFromUI();
|
||||||
void UpdatCCPMUIFromOptions();
|
void UpdateCCPMUIFromOptions();
|
||||||
|
|
||||||
void SetUIComponentVisibilities();
|
void SetUIComponentVisibilities();
|
||||||
void ccpmChannelCheck();
|
void ccpmChannelCheck();
|
||||||
@ -143,8 +144,6 @@ private:
|
|||||||
void enableSwashplateLevellingControl(bool state);
|
void enableSwashplateLevellingControl(bool state);
|
||||||
void setSwashplateLevel(int percent);
|
void setSwashplateLevel(int percent);
|
||||||
void SwashLvlSpinBoxChanged(int value);
|
void SwashLvlSpinBoxChanged(int value);
|
||||||
void FocusChanged(QWidget *oldFocus, QWidget *newFocus);
|
|
||||||
|
|
||||||
virtual void refreshValues() {}; // Not used
|
virtual void refreshValues() {}; // Not used
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<file>images/coptercontrol.svg</file>
|
<file>images/coptercontrol.svg</file>
|
||||||
<file>images/hw_config.png</file>
|
<file>images/hw_config.png</file>
|
||||||
<file>images/gyroscope.png</file>
|
<file>images/gyroscope.png</file>
|
||||||
|
<file>images/TX.svg</file>
|
||||||
<file>images/camera.png</file>
|
<file>images/camera.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -102,6 +102,8 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent)
|
|||||||
onAutopilotConnect();
|
onAutopilotConnect();
|
||||||
|
|
||||||
help = 0;
|
help = 0;
|
||||||
|
connect(ftw,SIGNAL(currentAboutToShow(int,bool*)),this,SLOT(tabAboutToChange(int,bool*)));//,Qt::BlockingQueuedConnection);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigGadgetWidget::~ConfigGadgetWidget()
|
ConfigGadgetWidget::~ConfigGadgetWidget()
|
||||||
@ -118,6 +120,15 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigGadgetWidget::onAutopilotDisconnect() {
|
void ConfigGadgetWidget::onAutopilotDisconnect() {
|
||||||
|
ftw->setCurrentIndex(ConfigGadgetWidget::hardware);
|
||||||
|
ftw->removeTab(ConfigGadgetWidget::ins);
|
||||||
|
QWidget *qwd = new DefaultAttitudeWidget(this);
|
||||||
|
ftw->insertTab(ConfigGadgetWidget::ins, qwd, QIcon(":/configgadget/images/AHRS-v1.3.png"), QString("INS"));
|
||||||
|
ftw->removeTab(ConfigGadgetWidget::hardware);
|
||||||
|
qwd = new DefaultHwSettingsWidget(this);
|
||||||
|
ftw->insertTab(ConfigGadgetWidget::hardware, qwd, QIcon(":/configgadget/images/hw_config.png"), QString("HW Settings"));
|
||||||
|
ftw->setCurrentIndex(ConfigGadgetWidget::hardware);
|
||||||
|
|
||||||
emit autopilotDisconnected();
|
emit autopilotDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,5 +167,24 @@ void ConfigGadgetWidget::onAutopilotConnect() {
|
|||||||
emit autopilotConnected();
|
emit autopilotConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigGadgetWidget::tabAboutToChange(int i,bool * proceed)
|
||||||
|
{
|
||||||
|
Q_UNUSED(i);
|
||||||
|
*proceed=true;
|
||||||
|
ConfigTaskWidget * wid=qobject_cast<ConfigTaskWidget *>(ftw->currentWidget());
|
||||||
|
if(!wid)
|
||||||
|
return;
|
||||||
|
if(wid->isDirty())
|
||||||
|
{
|
||||||
|
int ans=QMessageBox::warning(this,tr("Unsaved changes"),tr("The tab you are leaving has unsaved changes,"
|
||||||
|
"if you proceed they will be lost."
|
||||||
|
"Do you still want to proceed?"),QMessageBox::Yes,QMessageBox::No);
|
||||||
|
if(ans==QMessageBox::No)
|
||||||
|
*proceed=false;
|
||||||
|
else
|
||||||
|
wid->setDirty(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,10 +37,10 @@
|
|||||||
//#include <QtWebKit/QWebView>
|
//#include <QtWebKit/QWebView>
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
#include "utils/pathutils.h"
|
#include "utils/pathutils.h"
|
||||||
|
#include <QMessageBox>
|
||||||
//#include "fancytabwidget.h"
|
//#include "fancytabwidget.h"
|
||||||
#include "utils/mytabbedstackwidget.h"
|
#include "utils/mytabbedstackwidget.h"
|
||||||
|
#include "configtaskwidget.h"
|
||||||
|
|
||||||
class ConfigGadgetWidget: public QWidget
|
class ConfigGadgetWidget: public QWidget
|
||||||
{
|
{
|
||||||
@ -55,6 +55,7 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void onAutopilotConnect();
|
void onAutopilotConnect();
|
||||||
void onAutopilotDisconnect();
|
void onAutopilotDisconnect();
|
||||||
|
void tabAboutToChange(int i,bool *);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void autopilotConnected();
|
void autopilotConnected();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file configservowidget.cpp
|
* @file configinputwidget.cpp
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
@ -38,614 +38,233 @@
|
|||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <utils/stylehelper.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "manualcontrolsettings.h"
|
#define ACCESS_MIN_MOVE -6
|
||||||
|
#define ACCESS_MAX_MOVE 6
|
||||||
|
#define STICK_MIN_MOVE -8
|
||||||
|
#define STICK_MAX_MOVE 8
|
||||||
|
|
||||||
ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent),wizardStep(wizardNone),loop(NULL),skipflag(false),transmitterType(heli)
|
||||||
{
|
{
|
||||||
|
manualCommandObj = ManualControlCommand::GetInstance(getObjectManager());
|
||||||
|
manualSettingsObj = ManualControlSettings::GetInstance(getObjectManager());
|
||||||
|
receiverActivityObj=ReceiverActivity::GetInstance(getObjectManager());
|
||||||
m_config = new Ui_InputWidget();
|
m_config = new Ui_InputWidget();
|
||||||
m_config->setupUi(this);
|
m_config->setupUi(this);
|
||||||
|
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
setupButtons(m_config->saveRCInputToRAM,m_config->saveRCInputToSD);
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
|
||||||
|
|
||||||
// First of all, put all the channel widgets into lists, so that we can
|
unsigned int index=0;
|
||||||
// manipulate those:
|
foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames())
|
||||||
|
{
|
||||||
|
Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM);
|
||||||
inMaxLabels << m_config->ch0Max
|
inputChannelForm * inp=new inputChannelForm(this,index==0);
|
||||||
<< m_config->ch1Max
|
m_config->channelSettings->layout()->addWidget(inp);
|
||||||
<< m_config->ch2Max
|
inp->ui->channelName->setText(name);
|
||||||
<< m_config->ch3Max
|
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelGroups",inp->ui->channelGroup,index);
|
||||||
<< m_config->ch4Max
|
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNumber",inp->ui->channelNumber,index);
|
||||||
<< m_config->ch5Max
|
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMin",inp->ui->channelMin,index);
|
||||||
<< m_config->ch6Max
|
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNeutral",inp->ui->channelNeutral,index);
|
||||||
<< m_config->ch7Max;
|
addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMax",inp->ui->channelMax,index);
|
||||||
|
++index;
|
||||||
inMinLabels << m_config->ch0Min
|
|
||||||
<< m_config->ch1Min
|
|
||||||
<< m_config->ch2Min
|
|
||||||
<< m_config->ch3Min
|
|
||||||
<< m_config->ch4Min
|
|
||||||
<< m_config->ch5Min
|
|
||||||
<< m_config->ch6Min
|
|
||||||
<< m_config->ch7Min;
|
|
||||||
|
|
||||||
inSliders << m_config->inSlider0
|
|
||||||
<< m_config->inSlider1
|
|
||||||
<< m_config->inSlider2
|
|
||||||
<< m_config->inSlider3
|
|
||||||
<< m_config->inSlider4
|
|
||||||
<< m_config->inSlider5
|
|
||||||
<< m_config->inSlider6
|
|
||||||
<< m_config->inSlider7;
|
|
||||||
|
|
||||||
inRevCheckboxes << m_config->ch0Rev
|
|
||||||
<< m_config->ch1Rev
|
|
||||||
<< m_config->ch2Rev
|
|
||||||
<< m_config->ch3Rev
|
|
||||||
<< m_config->ch4Rev
|
|
||||||
<< m_config->ch5Rev
|
|
||||||
<< m_config->ch6Rev
|
|
||||||
<< m_config->ch7Rev;
|
|
||||||
|
|
||||||
inChannelAssign << m_config->ch0Assign
|
|
||||||
<< m_config->ch1Assign
|
|
||||||
<< m_config->ch2Assign
|
|
||||||
<< m_config->ch3Assign
|
|
||||||
<< m_config->ch4Assign
|
|
||||||
<< m_config->ch5Assign
|
|
||||||
<< m_config->ch6Assign
|
|
||||||
<< m_config->ch7Assign;
|
|
||||||
|
|
||||||
// Now connect the widget to the ManualControlCommand / Channel UAVObject
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlCommand")));
|
|
||||||
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateChannels(UAVObject*)));
|
|
||||||
|
|
||||||
// Register for ManualControlSettings changes:
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlSettings")));
|
|
||||||
connect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(refreshValues()));
|
|
||||||
|
|
||||||
|
|
||||||
// Get the receiver types supported by OpenPilot and fill the corresponding
|
|
||||||
// dropdown menu:
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlSettings")));
|
|
||||||
UAVObjectField * field;
|
|
||||||
// Fill in the dropdown menus for the channel RC Input assignement.
|
|
||||||
QStringList channelsList;
|
|
||||||
channelsList << "None";
|
|
||||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
|
||||||
foreach (UAVObjectField* field, fieldList) {
|
|
||||||
if (field->getUnits().contains("channel")) {
|
|
||||||
channelsList.append(field->getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_config->ch0Assign->addItems(channelsList);
|
connect(m_config->configurationWizard,SIGNAL(clicked()),this,SLOT(goToWizard()));
|
||||||
m_config->ch1Assign->addItems(channelsList);
|
connect(m_config->runCalibration,SIGNAL(toggled(bool)),this, SLOT(simpleCalibration(bool)));
|
||||||
m_config->ch2Assign->addItems(channelsList);
|
|
||||||
m_config->ch3Assign->addItems(channelsList);
|
|
||||||
m_config->ch4Assign->addItems(channelsList);
|
|
||||||
m_config->ch5Assign->addItems(channelsList);
|
|
||||||
m_config->ch6Assign->addItems(channelsList);
|
|
||||||
m_config->ch7Assign->addItems(channelsList);
|
|
||||||
|
|
||||||
// And the flight mode settings:
|
connect(m_config->wzNext,SIGNAL(clicked()),this,SLOT(wzNext()));
|
||||||
field = obj->getField(QString("FlightModePosition"));
|
connect(m_config->wzCancel,SIGNAL(clicked()),this,SLOT(wzCancel()));
|
||||||
m_config->fmsModePos1->addItems(field->getOptions());
|
connect(m_config->wzBack,SIGNAL(clicked()),this,SLOT(wzBack()));
|
||||||
m_config->fmsModePos2->addItems(field->getOptions());
|
|
||||||
m_config->fmsModePos3->addItems(field->getOptions());
|
|
||||||
field = obj->getField(QString("Stabilization1Settings"));
|
|
||||||
channelsList.clear();
|
|
||||||
channelsList.append(field->getOptions());
|
|
||||||
m_config->fmsSsPos1Roll->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos1Pitch->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos1Yaw->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos2Roll->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos2Pitch->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos2Yaw->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos3Roll->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos3Pitch->addItems(channelsList);
|
|
||||||
m_config->fmsSsPos3Yaw->addItems(channelsList);
|
|
||||||
|
|
||||||
// And the Armin configurations:
|
m_config->stackedWidget->setCurrentIndex(0);
|
||||||
field = obj->getField(QString("Arming"));
|
addUAVObjectToWidgetRelation("ManualControlSettings","FlightModePosition",m_config->fmsModePos1,0);
|
||||||
m_config->armControl->clear();
|
addUAVObjectToWidgetRelation("ManualControlSettings","FlightModePosition",m_config->fmsModePos2,1);
|
||||||
m_config->armControl->addItems(field->getOptions());
|
addUAVObjectToWidgetRelation("ManualControlSettings","FlightModePosition",m_config->fmsModePos3,2);
|
||||||
|
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization1Settings",m_config->fmsSsPos1Roll,"Roll");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization2Settings",m_config->fmsSsPos2Roll,"Roll");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization3Settings",m_config->fmsSsPos3Roll,"Roll");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization1Settings",m_config->fmsSsPos1Pitch,"Pitch");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization2Settings",m_config->fmsSsPos2Pitch,"Pitch");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization3Settings",m_config->fmsSsPos3Pitch,"Pitch");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization1Settings",m_config->fmsSsPos1Yaw,"Yaw");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization2Settings",m_config->fmsSsPos2Yaw,"Yaw");
|
||||||
|
addUAVObjectToWidgetRelation("ManualControlSettings","Stabilization3Settings",m_config->fmsSsPos3Yaw,"Yaw");
|
||||||
|
|
||||||
connect(m_config->saveRCInputToSD, SIGNAL(clicked()), this, SLOT(saveRCInputObject()));
|
addUAVObjectToWidgetRelation("ManualControlSettings","Arming",m_config->armControl);
|
||||||
connect(m_config->saveRCInputToRAM, SIGNAL(clicked()), this, SLOT(sendRCInputUpdate()));
|
addUAVObjectToWidgetRelation("ManualControlSettings","ArmedTimeout",m_config->armTimeout,0,1000);
|
||||||
|
connect( ManualControlCommand::GetInstance(getObjectManager()),SIGNAL(objectUpdated(UAVObject*)),this,SLOT(moveFMSlider()));
|
||||||
enableControls(false);
|
enableControls(false);
|
||||||
refreshValues();
|
|
||||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect()));
|
|
||||||
connect(parent, SIGNAL(autopilotDisconnected()), this, SLOT(onAutopilotDisconnect()));
|
|
||||||
|
|
||||||
connect(m_config->ch0Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch1Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch2Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch3Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch4Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch5Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch6Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->ch7Rev, SIGNAL(toggled(bool)), this, SLOT(reverseCheckboxClicked(bool)));
|
|
||||||
connect(m_config->doRCInputCalibration,SIGNAL(stateChanged(int)),this,SLOT(updateTips(int)));
|
|
||||||
firstUpdate = true;
|
|
||||||
|
|
||||||
|
populateWidgets();
|
||||||
|
refreshWidgetsValues();
|
||||||
// Connect the help button
|
// Connect the help button
|
||||||
connect(m_config->inputHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
connect(m_config->inputHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
updateTips(Qt::Unchecked);
|
|
||||||
|
|
||||||
|
m_config->graphicsView->setScene(new QGraphicsScene(this));
|
||||||
|
m_config->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
|
m_renderer = new QSvgRenderer();
|
||||||
|
QGraphicsScene *l_scene = m_config->graphicsView->scene();
|
||||||
|
m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor()));
|
||||||
|
if (QFile::exists(":/configgadget/images/TX.svg") && m_renderer->load(QString(":/configgadget/images/TX.svg")) && m_renderer->isValid())
|
||||||
|
{
|
||||||
|
l_scene->clear(); // Deletes all items contained in the scene as well.
|
||||||
|
|
||||||
|
m_txBackground = new QGraphicsSvgItem();
|
||||||
|
// All other items will be clipped to the shape of the background
|
||||||
|
m_txBackground->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||||
|
QGraphicsItem::ItemClipsToShape);
|
||||||
|
m_txBackground->setSharedRenderer(m_renderer);
|
||||||
|
m_txBackground->setElementId("background");
|
||||||
|
l_scene->addItem(m_txBackground);
|
||||||
|
|
||||||
|
m_txMainBody = new QGraphicsSvgItem();
|
||||||
|
m_txMainBody->setParentItem(m_txBackground);
|
||||||
|
m_txMainBody->setSharedRenderer(m_renderer);
|
||||||
|
m_txMainBody->setElementId("body");
|
||||||
|
l_scene->addItem(m_txMainBody);
|
||||||
|
|
||||||
|
m_txLeftStick = new QGraphicsSvgItem();
|
||||||
|
m_txLeftStick->setParentItem(m_txBackground);
|
||||||
|
m_txLeftStick->setSharedRenderer(m_renderer);
|
||||||
|
m_txLeftStick->setElementId("ljoy");
|
||||||
|
|
||||||
|
m_txRightStick = new QGraphicsSvgItem();
|
||||||
|
m_txRightStick->setParentItem(m_txBackground);
|
||||||
|
m_txRightStick->setSharedRenderer(m_renderer);
|
||||||
|
m_txRightStick->setElementId("rjoy");
|
||||||
|
|
||||||
|
m_txAccess0 = new QGraphicsSvgItem();
|
||||||
|
m_txAccess0->setParentItem(m_txBackground);
|
||||||
|
m_txAccess0->setSharedRenderer(m_renderer);
|
||||||
|
m_txAccess0->setElementId("access0");
|
||||||
|
|
||||||
|
m_txAccess1 = new QGraphicsSvgItem();
|
||||||
|
m_txAccess1->setParentItem(m_txBackground);
|
||||||
|
m_txAccess1->setSharedRenderer(m_renderer);
|
||||||
|
m_txAccess1->setElementId("access1");
|
||||||
|
|
||||||
|
m_txAccess2 = new QGraphicsSvgItem();
|
||||||
|
m_txAccess2->setParentItem(m_txBackground);
|
||||||
|
m_txAccess2->setSharedRenderer(m_renderer);
|
||||||
|
m_txAccess2->setElementId("access2");
|
||||||
|
|
||||||
|
m_txFlightMode = new QGraphicsSvgItem();
|
||||||
|
m_txFlightMode->setParentItem(m_txBackground);
|
||||||
|
m_txFlightMode->setSharedRenderer(m_renderer);
|
||||||
|
m_txFlightMode->setElementId("flightModeCenter");
|
||||||
|
m_txFlightMode->setZValue(-10);
|
||||||
|
|
||||||
|
m_txArrows = new QGraphicsSvgItem();
|
||||||
|
m_txArrows->setParentItem(m_txBackground);
|
||||||
|
m_txArrows->setSharedRenderer(m_renderer);
|
||||||
|
m_txArrows->setElementId("arrows");
|
||||||
|
m_txArrows->setVisible(false);
|
||||||
|
|
||||||
|
QRectF orig=m_renderer->boundsOnElement("ljoy");
|
||||||
|
QMatrix Matrix = m_renderer->matrixForElement("ljoy");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txLeftStickOrig.translate(orig.x(),orig.y());
|
||||||
|
m_txLeftStick->setTransform(m_txLeftStickOrig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("arrows");
|
||||||
|
Matrix = m_renderer->matrixForElement("arrows");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txArrowsOrig.translate(orig.x(),orig.y());
|
||||||
|
m_txArrows->setTransform(m_txArrowsOrig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("body");
|
||||||
|
Matrix = m_renderer->matrixForElement("body");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txMainBodyOrig.translate(orig.x(),orig.y());
|
||||||
|
m_txMainBody->setTransform(m_txMainBodyOrig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("flightModeCenter");
|
||||||
|
Matrix = m_renderer->matrixForElement("flightModeCenter");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txFlightModeCOrig.translate(orig.x(),orig.y());
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeCOrig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("flightModeLeft");
|
||||||
|
Matrix = m_renderer->matrixForElement("flightModeLeft");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txFlightModeLOrig.translate(orig.x(),orig.y());
|
||||||
|
orig=m_renderer->boundsOnElement("flightModeRight");
|
||||||
|
Matrix = m_renderer->matrixForElement("flightModeRight");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txFlightModeROrig.translate(orig.x(),orig.y());
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("rjoy");
|
||||||
|
Matrix = m_renderer->matrixForElement("rjoy");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txRightStickOrig.translate(orig.x(),orig.y());
|
||||||
|
m_txRightStick->setTransform(m_txRightStickOrig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("access0");
|
||||||
|
Matrix = m_renderer->matrixForElement("access0");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txAccess0Orig.translate(orig.x(),orig.y());
|
||||||
|
m_txAccess0->setTransform(m_txAccess0Orig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("access1");
|
||||||
|
Matrix = m_renderer->matrixForElement("access1");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txAccess1Orig.translate(orig.x(),orig.y());
|
||||||
|
m_txAccess1->setTransform(m_txAccess1Orig,false);
|
||||||
|
|
||||||
|
orig=m_renderer->boundsOnElement("access2");
|
||||||
|
Matrix = m_renderer->matrixForElement("access2");
|
||||||
|
orig=Matrix.mapRect(orig);
|
||||||
|
m_txAccess2Orig.translate(orig.x(),orig.y());
|
||||||
|
m_txAccess2->setTransform(m_txAccess2Orig,true);
|
||||||
|
}
|
||||||
|
m_config->graphicsView->fitInView(m_txMainBody, Qt::KeepAspectRatio );
|
||||||
|
animate=new QTimer(this);
|
||||||
|
connect(animate,SIGNAL(timeout()),this,SLOT(moveTxControls()));
|
||||||
|
|
||||||
|
heliChannelOrder << ManualControlSettings::CHANNELGROUPS_COLLECTIVE <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_THROTTLE <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ROLL <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_PITCH <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_YAW <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_FLIGHTMODE <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY0 <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY1 <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY2;
|
||||||
|
|
||||||
|
acroChannelOrder << ManualControlSettings::CHANNELGROUPS_THROTTLE <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ROLL <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_PITCH <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_YAW <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_FLIGHTMODE <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY0 <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY1 <<
|
||||||
|
ManualControlSettings::CHANNELGROUPS_ACCESSORY2;
|
||||||
|
}
|
||||||
|
void ConfigInputWidget::resetTxControls()
|
||||||
|
{
|
||||||
|
|
||||||
|
m_txLeftStick->setTransform(m_txLeftStickOrig,false);
|
||||||
|
m_txRightStick->setTransform(m_txRightStickOrig,false);
|
||||||
|
m_txAccess0->setTransform(m_txAccess0Orig,false);
|
||||||
|
m_txAccess1->setTransform(m_txAccess1Orig,false);
|
||||||
|
m_txAccess2->setTransform(m_txAccess2Orig,false);
|
||||||
|
m_txFlightMode->setElementId("flightModeCenter");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeCOrig,false);
|
||||||
|
m_txArrows->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigInputWidget::~ConfigInputWidget()
|
ConfigInputWidget::~ConfigInputWidget()
|
||||||
{
|
{
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Slot called whenever we revert a signal
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::reverseCheckboxClicked(bool state)
|
|
||||||
{
|
|
||||||
QObject* obj = sender();
|
|
||||||
int i = inRevCheckboxes.indexOf((QCheckBox*)obj);
|
|
||||||
|
|
||||||
inSliders[i]->setInvertedAppearance(state);
|
|
||||||
int max = inMaxLabels[i]->text().toInt();
|
|
||||||
int min = inMinLabels[i]->text().toInt();
|
|
||||||
if ((state && (max>min)) ||
|
|
||||||
(!state && (max < min))) {
|
|
||||||
inMaxLabels[i]->setText(QString::number(min));
|
|
||||||
inMinLabels[i]->setText(QString::number(max));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************
|
|
||||||
|
|
||||||
/*
|
|
||||||
Enable or disable some controls depending on whether we are connected
|
|
||||||
or not to the board. Actually, this i mostly useless IMHO, I don't
|
|
||||||
know who added this into the code (Ed's note)
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::enableControls(bool enable)
|
|
||||||
{
|
|
||||||
//m_config->saveRCInputToRAM->setEnabled(enable);
|
|
||||||
m_config->saveRCInputToSD->setEnabled(enable);
|
|
||||||
m_config->doRCInputCalibration->setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
|
||||||
* Input settings
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
Request the current config from the board
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::refreshValues()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
//obj->requestUpdate();
|
|
||||||
UAVObjectField *field;
|
|
||||||
|
|
||||||
// Now update all the slider values:
|
|
||||||
|
|
||||||
UAVObjectField *field_max = obj->getField(QString("ChannelMax"));
|
|
||||||
UAVObjectField *field_min = obj->getField(QString("ChannelMin"));
|
|
||||||
UAVObjectField *field_neu = obj->getField(QString("ChannelNeutral"));
|
|
||||||
Q_ASSERT(field_max);
|
|
||||||
Q_ASSERT(field_min);
|
|
||||||
Q_ASSERT(field_neu);
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
QVariant max = field_max->getValue(i);
|
|
||||||
QVariant min = field_min->getValue(i);
|
|
||||||
QVariant neutral = field_neu->getValue(i);
|
|
||||||
inMaxLabels[i]->setText(max.toString());
|
|
||||||
inMinLabels[i]->setText(min.toString());
|
|
||||||
if (max.toInt()> min.toInt()) {
|
|
||||||
inRevCheckboxes[i]->setChecked(false);
|
|
||||||
inSliders[i]->setMaximum(max.toInt());
|
|
||||||
inSliders[i]->setMinimum(min.toInt());
|
|
||||||
} else {
|
|
||||||
inRevCheckboxes[i]->setChecked(true);
|
|
||||||
inSliders[i]->setMaximum(min.toInt());
|
|
||||||
inSliders[i]->setMinimum(max.toInt());
|
|
||||||
}
|
|
||||||
inSliders[i]->setValue(neutral.toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update receiver type
|
|
||||||
field = obj->getField(QString("InputMode"));
|
|
||||||
m_config->receiverType->setText(field->getValue().toString());
|
|
||||||
|
|
||||||
// Reset all channel assignement dropdowns:
|
|
||||||
foreach (QComboBox *combo, inChannelAssign) {
|
|
||||||
combo->setCurrentIndex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all channels assignements
|
|
||||||
QList<UAVObjectField *> fieldList = obj->getFields();
|
|
||||||
foreach (UAVObjectField *field, fieldList) {
|
|
||||||
if (field->getUnits().contains("channel"))
|
|
||||||
assignChannel(obj, field->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all the flight mode settingsin the relevant tab
|
|
||||||
field = obj->getField(QString("FlightModePosition"));
|
|
||||||
m_config->fmsModePos1->setCurrentIndex((m_config->fmsModePos1->findText(field->getValue(0).toString())));
|
|
||||||
m_config->fmsModePos2->setCurrentIndex((m_config->fmsModePos2->findText(field->getValue(1).toString())));
|
|
||||||
m_config->fmsModePos3->setCurrentIndex((m_config->fmsModePos3->findText(field->getValue(2).toString())));
|
|
||||||
|
|
||||||
field = obj->getField(QString("Stabilization1Settings"));
|
|
||||||
m_config->fmsSsPos1Roll->setCurrentIndex(m_config->fmsSsPos1Roll->findText(field->getValue(field->getElementNames().indexOf("Roll")).toString()));
|
|
||||||
m_config->fmsSsPos1Pitch->setCurrentIndex(m_config->fmsSsPos1Pitch->findText(field->getValue(field->getElementNames().indexOf("Pitch")).toString()));
|
|
||||||
m_config->fmsSsPos1Yaw->setCurrentIndex(m_config->fmsSsPos1Yaw->findText(field->getValue(field->getElementNames().indexOf("Yaw")).toString()));
|
|
||||||
field = obj->getField(QString("Stabilization2Settings"));
|
|
||||||
m_config->fmsSsPos2Roll->setCurrentIndex(m_config->fmsSsPos2Roll->findText(field->getValue(field->getElementNames().indexOf("Roll")).toString()));
|
|
||||||
m_config->fmsSsPos2Pitch->setCurrentIndex(m_config->fmsSsPos2Pitch->findText(field->getValue(field->getElementNames().indexOf("Pitch")).toString()));
|
|
||||||
m_config->fmsSsPos2Yaw->setCurrentIndex(m_config->fmsSsPos2Yaw->findText(field->getValue(field->getElementNames().indexOf("Yaw")).toString()));
|
|
||||||
field = obj->getField(QString("Stabilization3Settings"));
|
|
||||||
m_config->fmsSsPos3Roll->setCurrentIndex(m_config->fmsSsPos3Roll->findText(field->getValue(field->getElementNames().indexOf("Roll")).toString()));
|
|
||||||
m_config->fmsSsPos3Pitch->setCurrentIndex(m_config->fmsSsPos3Pitch->findText(field->getValue(field->getElementNames().indexOf("Pitch")).toString()));
|
|
||||||
m_config->fmsSsPos3Yaw->setCurrentIndex(m_config->fmsSsPos3Yaw->findText(field->getValue(field->getElementNames().indexOf("Yaw")).toString()));
|
|
||||||
|
|
||||||
// Load the arming settings
|
|
||||||
field = obj->getField(QString("Arming"));
|
|
||||||
m_config->armControl->setCurrentIndex(m_config->armControl->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("ArmedTimeout"));
|
|
||||||
m_config->armTimeout->setValue(field->getValue().toInt()/1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the config to the board, without saving to the SD card
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::sendRCInputUpdate()
|
|
||||||
{
|
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
// Now update all fields from the sliders:
|
|
||||||
QString fieldName = QString("ChannelMax");
|
|
||||||
UAVObjectField * field = obj->getField(fieldName);
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
field->setValue(inMaxLabels[i]->text().toInt(), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldName = QString("ChannelMin");
|
|
||||||
field = obj->getField(fieldName);
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
field->setValue(inMinLabels[i]->text().toInt(), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldName = QString("ChannelNeutral");
|
|
||||||
field = obj->getField(fieldName);
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
field->setValue(inSliders[i]->value(), i);
|
|
||||||
|
|
||||||
// Set Roll/Pitch/Yaw/Etc assignement:
|
|
||||||
// Rule: if two channels have the same setting (which is wrong!) the higher channel
|
|
||||||
// will get the setting.
|
|
||||||
|
|
||||||
// First, reset all channel assignements:
|
|
||||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
|
||||||
foreach (UAVObjectField* field, fieldList) {
|
|
||||||
if (field->getUnits().contains("channel")) {
|
|
||||||
field->setValue(field->getOptions().last());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then assign according to current GUI state:
|
|
||||||
if (m_config->ch0Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch0Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(0)); // -> This way we don't depend on channel naming convention
|
|
||||||
}
|
|
||||||
if (m_config->ch1Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch1Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(1));
|
|
||||||
}
|
|
||||||
if (m_config->ch2Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch2Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(2));
|
|
||||||
}
|
|
||||||
if (m_config->ch3Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch3Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(3));
|
|
||||||
}
|
|
||||||
if (m_config->ch4Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch4Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(4));
|
|
||||||
}
|
|
||||||
if (m_config->ch5Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch5Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(5));
|
|
||||||
}
|
|
||||||
if (m_config->ch6Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch6Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(6));
|
|
||||||
}
|
|
||||||
if (m_config->ch7Assign->currentIndex() != 0) {
|
|
||||||
field = obj->getField(m_config->ch7Assign->currentText());
|
|
||||||
field->setValue(field->getOptions().at(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send all the flight mode settings
|
|
||||||
field = obj->getField(QString("FlightModePosition"));
|
|
||||||
field->setValue(m_config->fmsModePos1->currentText(),0);
|
|
||||||
field->setValue(m_config->fmsModePos2->currentText(),1);
|
|
||||||
field->setValue(m_config->fmsModePos3->currentText(),2);
|
|
||||||
|
|
||||||
field = obj->getField(QString("Stabilization1Settings"));
|
|
||||||
field->setValue(m_config->fmsSsPos1Roll->currentText(), field->getElementNames().indexOf("Roll"));
|
|
||||||
field->setValue(m_config->fmsSsPos1Pitch->currentText(), field->getElementNames().indexOf("Pitch"));
|
|
||||||
field->setValue(m_config->fmsSsPos1Yaw->currentText(), field->getElementNames().indexOf("Yaw"));
|
|
||||||
field = obj->getField(QString("Stabilization2Settings"));
|
|
||||||
field->setValue(m_config->fmsSsPos2Roll->currentText(), field->getElementNames().indexOf("Roll"));
|
|
||||||
field->setValue(m_config->fmsSsPos2Pitch->currentText(), field->getElementNames().indexOf("Pitch"));
|
|
||||||
field->setValue(m_config->fmsSsPos2Yaw->currentText(), field->getElementNames().indexOf("Yaw"));
|
|
||||||
field = obj->getField(QString("Stabilization3Settings"));
|
|
||||||
field->setValue(m_config->fmsSsPos3Roll->currentText(), field->getElementNames().indexOf("Roll"));
|
|
||||||
field->setValue(m_config->fmsSsPos3Pitch->currentText(), field->getElementNames().indexOf("Pitch"));
|
|
||||||
field->setValue(m_config->fmsSsPos3Yaw->currentText(), field->getElementNames().indexOf("Yaw"));
|
|
||||||
|
|
||||||
// Save the arming settings
|
|
||||||
field = obj->getField(QString("Arming"));
|
|
||||||
field->setValue(m_config->armControl->currentText());
|
|
||||||
field = obj->getField(QString("ArmedTimeout"));
|
|
||||||
field->setValue(m_config->armTimeout->value()*1000);
|
|
||||||
|
|
||||||
// ... and send to the OP Board
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void ConfigInputWidget::resizeEvent(QResizeEvent *event)
|
||||||
Sends the config to the board and request saving into the SD card
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::saveRCInputObject()
|
|
||||||
{
|
{
|
||||||
// Send update so that the latest value is saved
|
QWidget::resizeEvent(event);
|
||||||
sendRCInputUpdate();
|
m_config->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio );
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
saveObjectToSD(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the dropdown option for a channel Input assignement
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::assignChannel(UAVDataObject *obj, QString str)
|
|
||||||
{
|
|
||||||
UAVObjectField* field = obj->getField(str);
|
|
||||||
QStringList options = field->getOptions();
|
|
||||||
switch (options.indexOf(field->getValue().toString())) {
|
|
||||||
case 0:
|
|
||||||
m_config->ch0Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
m_config->ch1Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
m_config->ch2Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
m_config->ch3Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
m_config->ch4Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
m_config->ch5Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
m_config->ch6Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
m_config->ch7Assign->setCurrentIndex(m_config->ch0Assign->findText(str));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the slider positions and min/max values
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void ConfigInputWidget::updateChannels(UAVObject* controlCommand)
|
|
||||||
{
|
|
||||||
|
|
||||||
QString fieldName = QString("Connected");
|
|
||||||
UAVObjectField *field = controlCommand->getField(fieldName);
|
|
||||||
if (field->getValue().toBool())
|
|
||||||
{
|
|
||||||
m_config->RCInputConnected->setText("RC Receiver connected");
|
|
||||||
m_config->lblMissingInputs->setText("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_config->RCInputConnected->setText("RC Receiver not connected or invalid input configuration (missing channels)");
|
|
||||||
receiverHelp();
|
|
||||||
}
|
|
||||||
if (m_config->doRCInputCalibration->isChecked()) {
|
|
||||||
if (firstUpdate) {
|
|
||||||
// Increase the data rate from the board so that the sliders
|
|
||||||
// move faster
|
|
||||||
UAVObject::Metadata mdata = controlCommand->getMetadata();
|
|
||||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
|
||||||
mccDataRate = mdata.flightTelemetryUpdatePeriod;
|
|
||||||
mdata.flightTelemetryUpdatePeriod = 150;
|
|
||||||
controlCommand->setMetadata(mdata);
|
|
||||||
|
|
||||||
// Also protect the user by setting all values to zero
|
|
||||||
// and making the ActuatorCommand object readonly
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
|
|
||||||
mdata = obj->getMetadata();
|
|
||||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
|
||||||
obj->setMetadata(mdata);
|
|
||||||
UAVObjectField *field = obj->getField("Channel");
|
|
||||||
for (uint i=0; i< field->getNumElements(); i++) {
|
|
||||||
field->setValue(0,i);
|
|
||||||
}
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
// OP-534: make sure the airframe can NEVER arm
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlSettings")));
|
|
||||||
field = obj->getField("Arming");
|
|
||||||
field->setValue("Always Disarmed");
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
// Last, make sure the user won't apply/save during calibration
|
|
||||||
m_config->saveRCInputToRAM->setEnabled(false);
|
|
||||||
m_config->saveRCInputToSD->setEnabled(false);
|
|
||||||
|
|
||||||
// Reset all slider values to zero
|
|
||||||
field = controlCommand->getField(QString("Channel"));
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
updateChannelInSlider(inSliders[i], inMinLabels[i], inMaxLabels[i], field->getValue(i).toInt(),inRevCheckboxes[i]->isChecked());
|
|
||||||
firstUpdate = false;
|
|
||||||
// Tell a few things to the user:
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setText(tr("Arming Settings are now set to Always Disarmed for your safety."));
|
|
||||||
msgBox.setDetailedText(tr("You will have to reconfigure arming settings yourself afterwards."));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
field = controlCommand->getField(QString("Channel"));
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
updateChannelInSlider(inSliders[i], inMinLabels[i], inMaxLabels[i], field->getValue(i).toInt(),inRevCheckboxes[i]->isChecked());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!firstUpdate) {
|
|
||||||
// Restore original data rate from the board:
|
|
||||||
UAVObject::Metadata mdata = controlCommand->getMetadata();
|
|
||||||
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
|
||||||
mdata.flightTelemetryUpdatePeriod = mccDataRate;
|
|
||||||
controlCommand->setMetadata(mdata);
|
|
||||||
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorCommand")));
|
|
||||||
mdata = obj->getMetadata();
|
|
||||||
mdata.flightAccess = UAVObject::ACCESS_READWRITE;
|
|
||||||
obj->setMetadata(mdata);
|
|
||||||
|
|
||||||
// Set some slider values to better defaults
|
|
||||||
// Find some channels first
|
|
||||||
int throttleChannel = -1;
|
|
||||||
int fmChannel = -1;
|
|
||||||
for (int i=0; i < inChannelAssign.length(); i++) {
|
|
||||||
if (inChannelAssign.at(i)->currentText() == "Throttle") {
|
|
||||||
// TODO: this is very ugly, because this relies on the name of the
|
|
||||||
// channel input, everywhere else in the gadget we don't rely on the
|
|
||||||
// naming...
|
|
||||||
throttleChannel = i;
|
|
||||||
}
|
|
||||||
if (inChannelAssign.at(i)->currentText() == "FlightMode") {
|
|
||||||
// TODO: this is very ugly, because this relies on the name of the
|
|
||||||
// channel input, everywhere else in the gadget we don't rely on the
|
|
||||||
// naming...
|
|
||||||
fmChannel = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throttle neutral defaults to 2% of range
|
|
||||||
if (throttleChannel > -1) {
|
|
||||||
inSliders.at(throttleChannel)->setValue(
|
|
||||||
inSliders.at(throttleChannel)->minimum() +
|
|
||||||
(inSliders.at(throttleChannel)->maximum()-
|
|
||||||
inSliders.at(throttleChannel)->minimum())*0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flight mode at 50% of range:
|
|
||||||
if (fmChannel > -1) {
|
|
||||||
inSliders.at(fmChannel)->setValue(
|
|
||||||
inSliders.at(fmChannel)->minimum()+
|
|
||||||
(inSliders.at(fmChannel)->maximum()-
|
|
||||||
inSliders.at(fmChannel)->minimum())*0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_config->saveRCInputToRAM->setEnabled(true);
|
|
||||||
m_config->saveRCInputToSD->setEnabled(true);
|
|
||||||
}
|
|
||||||
firstUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Update the Flight mode channel slider
|
|
||||||
ManualControlSettings * manualSettings = ManualControlSettings::GetInstance(getObjectManager());
|
|
||||||
ManualControlSettings::DataFields manualSettingsData = manualSettings->getData();
|
|
||||||
uint chIndex = manualSettingsData.FlightMode;
|
|
||||||
if (chIndex < manualSettings->FLIGHTMODE_NONE) {
|
|
||||||
float valueScaled;
|
|
||||||
|
|
||||||
int chMin = manualSettingsData.ChannelMin[chIndex];
|
|
||||||
int chMax = manualSettingsData.ChannelMax[chIndex];
|
|
||||||
int chNeutral = manualSettingsData.ChannelNeutral[chIndex];
|
|
||||||
|
|
||||||
int value = controlCommand->getField("Channel")->getValue(chIndex).toInt();
|
|
||||||
if ((chMax > chMin && value >= chNeutral) || (chMin > chMax && value <= chNeutral))
|
|
||||||
{
|
|
||||||
if (chMax != chNeutral)
|
|
||||||
valueScaled = (float)(value - chNeutral) / (float)(chMax - chNeutral);
|
|
||||||
else
|
|
||||||
valueScaled = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (chMin != chNeutral)
|
|
||||||
valueScaled = (float)(value - chNeutral) / (float)(chNeutral - chMin);
|
|
||||||
else
|
|
||||||
valueScaled = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(valueScaled < -(1.0 / 3.0))
|
|
||||||
m_config->fmsSlider->setValue(-100);
|
|
||||||
else if (valueScaled > (1.0/3.0))
|
|
||||||
m_config->fmsSlider->setValue(100);
|
|
||||||
else
|
|
||||||
m_config->fmsSlider->setValue(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigInputWidget::updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value, bool reversed)
|
|
||||||
{
|
|
||||||
if (!slider || !min || !max)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (firstUpdate) {
|
|
||||||
// Reset all the min/max values of the progress bar since we are starting the calibration.
|
|
||||||
slider->setMaximum(value);
|
|
||||||
slider->setMinimum(value);
|
|
||||||
slider->setValue(value);
|
|
||||||
max->setText(QString::number(value));
|
|
||||||
min->setText(QString::number(value));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value > 0) {
|
|
||||||
// avoids glitches...
|
|
||||||
if (value > slider->maximum()) {
|
|
||||||
slider->setMaximum(value);
|
|
||||||
if (reversed)
|
|
||||||
min->setText(QString::number(value));
|
|
||||||
else
|
|
||||||
max->setText(QString::number(value));
|
|
||||||
}
|
|
||||||
if (value < slider->minimum()) {
|
|
||||||
slider->setMinimum(value);
|
|
||||||
if (reversed)
|
|
||||||
max->setText(QString::number(value));
|
|
||||||
else
|
|
||||||
min->setText(QString::number(value));
|
|
||||||
}
|
|
||||||
slider->setValue(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigInputWidget::openHelp()
|
void ConfigInputWidget::openHelp()
|
||||||
@ -653,77 +272,1147 @@ void ConfigInputWidget::openHelp()
|
|||||||
|
|
||||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Input+Configuration", QUrl::StrictMode) );
|
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Input+Configuration", QUrl::StrictMode) );
|
||||||
}
|
}
|
||||||
void ConfigInputWidget::receiverHelp()
|
void ConfigInputWidget::goToWizard()
|
||||||
{
|
{
|
||||||
QString unassigned;
|
QMessageBox msgBox;
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
msgBox.setText(tr("Arming Settings are now set to Always Disarmed for your safety."));
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
msgBox.setDetailedText(tr("You will have to reconfigure arming settings yourself afterwards."));
|
||||||
UAVDataObject* controlCommand = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ManualControlSettings")));
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
UAVObjectField *field;
|
msgBox.exec();
|
||||||
|
wizardSetUpStep(wizardWelcome);
|
||||||
field= controlCommand->getField("Roll");
|
m_config->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio );
|
||||||
if(field->getValue().toString()=="None")
|
|
||||||
unassigned.append("Roll");
|
|
||||||
|
|
||||||
field =controlCommand->getField("Pitch");
|
|
||||||
if(field->getValue().toString()=="None")
|
|
||||||
{
|
|
||||||
if(unassigned.length()>0)
|
|
||||||
unassigned.append(", ");
|
|
||||||
unassigned.append("Pitch");
|
|
||||||
}
|
|
||||||
|
|
||||||
field =controlCommand->getField("Yaw");
|
|
||||||
if(field->getValue().toString()=="None")
|
|
||||||
{
|
|
||||||
if(unassigned.length()>0)
|
|
||||||
unassigned.append(", ");
|
|
||||||
unassigned.append("Yaw");
|
|
||||||
}
|
|
||||||
|
|
||||||
field =controlCommand->getField("Throttle");
|
|
||||||
if(field->getValue().toString()=="None")
|
|
||||||
{
|
|
||||||
if(unassigned.length()>0)
|
|
||||||
unassigned.append(", ");
|
|
||||||
unassigned.append("Throttle");
|
|
||||||
}
|
|
||||||
|
|
||||||
field =controlCommand->getField("FlightMode");
|
|
||||||
if(field->getValue().toString()=="None")
|
|
||||||
{
|
|
||||||
if(unassigned.length()>0)
|
|
||||||
unassigned.append(", ");
|
|
||||||
unassigned.append("FlightMode");
|
|
||||||
}
|
|
||||||
if(unassigned.length()>0)
|
|
||||||
m_config->lblMissingInputs->setText(QString("Channels left to assign: ")+unassigned);
|
|
||||||
else
|
|
||||||
m_config->lblMissingInputs->setText("");
|
|
||||||
}
|
}
|
||||||
void ConfigInputWidget::updateTips(int value)
|
|
||||||
|
void ConfigInputWidget::wzCancel()
|
||||||
{
|
{
|
||||||
if(value==Qt::Checked)
|
dimOtherControls(false);
|
||||||
|
manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata());
|
||||||
|
m_config->stackedWidget->setCurrentIndex(0);
|
||||||
|
|
||||||
|
if(wizardStep != wizardNone)
|
||||||
|
wizardTearDownStep(wizardStep);
|
||||||
|
wizardStep=wizardNone;
|
||||||
|
|
||||||
|
// Load settings back from beginning of wizard
|
||||||
|
manualSettingsObj->setData(previousManualSettingsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wzNext()
|
||||||
|
{
|
||||||
|
// In identify sticks mode the next button can indicate
|
||||||
|
// channel advance
|
||||||
|
if(wizardStep != wizardNone &&
|
||||||
|
wizardStep != wizardIdentifySticks)
|
||||||
|
wizardTearDownStep(wizardStep);
|
||||||
|
|
||||||
|
// State transitions for next button
|
||||||
|
switch(wizardStep) {
|
||||||
|
case wizardWelcome:
|
||||||
|
wizardSetUpStep(wizardChooseMode);
|
||||||
|
break;
|
||||||
|
case wizardChooseMode:
|
||||||
|
wizardSetUpStep(wizardChooseType);
|
||||||
|
break;
|
||||||
|
case wizardChooseType:
|
||||||
|
wizardSetUpStep(wizardIdentifySticks);
|
||||||
|
break;
|
||||||
|
case wizardIdentifySticks:
|
||||||
|
nextChannel();
|
||||||
|
if(currentChannelNum==-1) { // Gone through all channels
|
||||||
|
wizardTearDownStep(wizardIdentifySticks);
|
||||||
|
wizardSetUpStep(wizardIdentifyCenter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wizardIdentifyCenter:
|
||||||
|
wizardSetUpStep(wizardIdentifyLimits);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyLimits:
|
||||||
|
wizardSetUpStep(wizardIdentifyInverted);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyInverted:
|
||||||
|
wizardSetUpStep(wizardFinish);
|
||||||
|
break;
|
||||||
|
case wizardFinish:
|
||||||
|
setTxMovement(nothing);
|
||||||
|
manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata());
|
||||||
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]=
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+
|
||||||
|
((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]-
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
m_config->stackedWidget->setCurrentIndex(0);
|
||||||
|
wizardStep=wizardNone;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wzBack()
|
||||||
|
{
|
||||||
|
if(wizardStep != wizardNone &&
|
||||||
|
wizardStep != wizardIdentifySticks)
|
||||||
|
wizardTearDownStep(wizardStep);
|
||||||
|
|
||||||
|
// State transitions for next button
|
||||||
|
switch(wizardStep) {
|
||||||
|
case wizardChooseMode:
|
||||||
|
wizardSetUpStep(wizardWelcome);
|
||||||
|
break;
|
||||||
|
case wizardChooseType:
|
||||||
|
wizardSetUpStep(wizardChooseMode);
|
||||||
|
break;
|
||||||
|
case wizardIdentifySticks:
|
||||||
|
prevChannel();
|
||||||
|
if(currentChannelNum == -1) {
|
||||||
|
wizardTearDownStep(wizardIdentifySticks);
|
||||||
|
wizardSetUpStep(wizardChooseType);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wizardIdentifyCenter:
|
||||||
|
wizardSetUpStep(wizardIdentifySticks);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyLimits:
|
||||||
|
wizardSetUpStep(wizardIdentifyCenter);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyInverted:
|
||||||
|
wizardSetUpStep(wizardIdentifyLimits);
|
||||||
|
break;
|
||||||
|
case wizardFinish:
|
||||||
|
wizardSetUpStep(wizardIdentifyInverted);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
|
||||||
|
{
|
||||||
|
switch(step) {
|
||||||
|
case wizardWelcome:
|
||||||
|
m_config->graphicsView->setVisible(false);
|
||||||
|
setTxMovement(nothing);
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED;
|
||||||
|
previousManualSettingsData = manualSettingsData;
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
m_config->wzText->setText(tr("Welcome to the inputs configuration wizard.\n"
|
||||||
|
"Please follow the instructions on the screen and only move your controls when asked to.\n"
|
||||||
|
"Make sure you already configured your hardware settings on the proper tab and restarted your board.\n"
|
||||||
|
"At any time you can press 'back' to return to the previous screeen or 'Cancel' to cancel the wizard.\n"));
|
||||||
|
m_config->stackedWidget->setCurrentIndex(1);
|
||||||
|
m_config->wzBack->setEnabled(false);
|
||||||
|
break;
|
||||||
|
case wizardChooseMode:
|
||||||
{
|
{
|
||||||
m_config->ch0Cur->setToolTip("Current channel value");
|
m_config->graphicsView->setVisible(true);
|
||||||
m_config->ch1Cur->setToolTip("Current channel value");
|
setTxMovement(nothing);
|
||||||
m_config->ch2Cur->setToolTip("Current channel value");
|
m_config->wzText->setText(tr("Please choose your transmiter type.\n"
|
||||||
m_config->ch3Cur->setToolTip("Current channel value");
|
"Mode 1 means your throttle stick is on the right\n"
|
||||||
m_config->ch4Cur->setToolTip("Current channel value");
|
"Mode 2 means your throttle stick is on the left\n"));
|
||||||
m_config->ch5Cur->setToolTip("Current channel value");
|
m_config->wzBack->setEnabled(true);
|
||||||
m_config->ch6Cur->setToolTip("Current channel value");
|
QRadioButton * mode1=new QRadioButton(tr("Mode 1"),this);
|
||||||
m_config->ch7Cur->setToolTip("Current channel value");
|
QRadioButton * mode2=new QRadioButton(tr("Mode 2"),this);
|
||||||
|
mode2->setChecked(true);
|
||||||
|
extraWidgets.clear();
|
||||||
|
extraWidgets.append(mode1);
|
||||||
|
extraWidgets.append(mode2);
|
||||||
|
m_config->checkBoxesLayout->layout()->addWidget(mode1);
|
||||||
|
m_config->checkBoxesLayout->layout()->addWidget(mode2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wizardChooseType:
|
||||||
|
{
|
||||||
|
m_config->wzText->setText(tr("Please choose your transmiter mode.\n"
|
||||||
|
"Acro means normal transmitter\n"
|
||||||
|
"Heli means there is a collective pitch and throttle input\n"
|
||||||
|
"If you are using a heli transmitter please engage throttle hold now please.\n"));
|
||||||
|
m_config->wzBack->setEnabled(true);
|
||||||
|
QRadioButton * typeAcro=new QRadioButton(tr("Acro"),this);
|
||||||
|
QRadioButton * typeHeli=new QRadioButton(tr("Heli"),this);
|
||||||
|
typeAcro->setChecked(true);
|
||||||
|
typeHeli->setChecked(false);
|
||||||
|
extraWidgets.clear();
|
||||||
|
extraWidgets.append(typeAcro);
|
||||||
|
extraWidgets.append(typeHeli);
|
||||||
|
m_config->checkBoxesLayout->layout()->addWidget(typeAcro);
|
||||||
|
m_config->checkBoxesLayout->layout()->addWidget(typeHeli);
|
||||||
|
wizardStep=wizardChooseType;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wizardIdentifySticks:
|
||||||
|
usedChannels.clear();
|
||||||
|
currentChannelNum=-1;
|
||||||
|
nextChannel();
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
connect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls()));
|
||||||
|
m_config->wzNext->setEnabled(false);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyCenter:
|
||||||
|
setTxMovement(centerAll);
|
||||||
|
m_config->wzText->setText(QString(tr("Please center all control controls and press next when ready (if your FlightMode switch has only two positions, leave it on either position)")));
|
||||||
|
break;
|
||||||
|
case wizardIdentifyLimits:
|
||||||
|
{
|
||||||
|
dimOtherControls(false);
|
||||||
|
setTxMovement(moveAll);
|
||||||
|
m_config->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions and press next when ready")));
|
||||||
|
fastMdata();
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
for(uint i=0;i<ManualControlSettings::CHANNELMAX_NUMELEM;++i)
|
||||||
|
{
|
||||||
|
manualSettingsData.ChannelMin[i]=manualSettingsData.ChannelNeutral[i];
|
||||||
|
manualSettingsData.ChannelMax[i]=manualSettingsData.ChannelNeutral[i];
|
||||||
|
}
|
||||||
|
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wizardIdentifyInverted:
|
||||||
|
dimOtherControls(true);
|
||||||
|
setTxMovement(nothing);
|
||||||
|
extraWidgets.clear();
|
||||||
|
foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames())
|
||||||
|
{
|
||||||
|
if(!name.contains("Access") && !name.contains("Flight"))
|
||||||
|
{
|
||||||
|
QCheckBox * cb=new QCheckBox(name,this);
|
||||||
|
extraWidgets.append(cb);
|
||||||
|
m_config->checkBoxesLayout->layout()->addWidget(cb);
|
||||||
|
connect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
m_config->wzText->setText(QString(tr("Please check the picture below and check all the sticks which show an inverted movement and press next when ready")));
|
||||||
|
fastMdata();
|
||||||
|
break;
|
||||||
|
case wizardFinish:
|
||||||
|
foreach(QWidget * wd,extraWidgets)
|
||||||
|
{
|
||||||
|
QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||||
|
if(cb)
|
||||||
|
{
|
||||||
|
disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
delete cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extraWidgets.clear();
|
||||||
|
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
m_config->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture below mimics your sticks movement.\n"
|
||||||
|
"This new settings aren't saved to the board yet, after pressing next you will go to the initial screen where you can do that.")));
|
||||||
|
fastMdata();
|
||||||
|
|
||||||
|
manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]=
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+
|
||||||
|
((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]-
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_ASSERT(0);
|
||||||
|
}
|
||||||
|
wizardStep = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
|
||||||
|
{
|
||||||
|
QRadioButton * mode, * type;
|
||||||
|
Q_ASSERT(step == wizardStep);
|
||||||
|
switch(step) {
|
||||||
|
case wizardWelcome:
|
||||||
|
break;
|
||||||
|
case wizardChooseMode:
|
||||||
|
mode=qobject_cast<QRadioButton *>(extraWidgets.at(0));
|
||||||
|
if(mode->isChecked())
|
||||||
|
transmitterMode=mode1;
|
||||||
|
else
|
||||||
|
transmitterMode=mode2;
|
||||||
|
delete extraWidgets.at(0);
|
||||||
|
delete extraWidgets.at(1);
|
||||||
|
extraWidgets.clear();
|
||||||
|
break;
|
||||||
|
case wizardChooseType:
|
||||||
|
type=qobject_cast<QRadioButton *>(extraWidgets.at(0));
|
||||||
|
if(type->isChecked())
|
||||||
|
transmitterType=acro;
|
||||||
|
else
|
||||||
|
transmitterType=heli;
|
||||||
|
delete extraWidgets.at(0);
|
||||||
|
delete extraWidgets.at(1);
|
||||||
|
extraWidgets.clear();
|
||||||
|
break;
|
||||||
|
case wizardIdentifySticks:
|
||||||
|
disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls()));
|
||||||
|
m_config->wzNext->setEnabled(true);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyCenter:
|
||||||
|
manualCommandData=manualCommandObj->getData();
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
for(unsigned int i=0;i<ManualControlCommand::CHANNEL_NUMELEM;++i)
|
||||||
|
{
|
||||||
|
manualSettingsData.ChannelNeutral[i]=manualCommandData.Channel[i];
|
||||||
|
}
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
break;
|
||||||
|
case wizardIdentifyLimits:
|
||||||
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
restoreMdata();
|
||||||
|
break;
|
||||||
|
case wizardIdentifyInverted:
|
||||||
|
foreach(QWidget * wd,extraWidgets)
|
||||||
|
{
|
||||||
|
QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||||
|
if(cb)
|
||||||
|
{
|
||||||
|
disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
delete cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extraWidgets.clear();
|
||||||
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
restoreMdata();
|
||||||
|
break;
|
||||||
|
case wizardFinish:
|
||||||
|
setTxMovement(nothing);
|
||||||
|
m_config->stackedWidget->setCurrentIndex(0);
|
||||||
|
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
restoreMdata();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set manual control command to fast updates
|
||||||
|
*/
|
||||||
|
void ConfigInputWidget::fastMdata()
|
||||||
|
{
|
||||||
|
manualControlMdata = manualCommandObj->getMetadata();
|
||||||
|
UAVObject::Metadata mdata = manualControlMdata;
|
||||||
|
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||||
|
mdata.flightTelemetryUpdatePeriod = 150;
|
||||||
|
manualCommandObj->setMetadata(mdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore previous update settings for manual control data
|
||||||
|
*/
|
||||||
|
void ConfigInputWidget::restoreMdata()
|
||||||
|
{
|
||||||
|
manualCommandObj->setMetadata(manualControlMdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void ConfigInputWidget::setupWizardWidget(int step)
|
||||||
|
//{
|
||||||
|
// if(step==wizardWelcome)
|
||||||
|
// {
|
||||||
|
// m_config->graphicsView->setVisible(false);
|
||||||
|
// setTxMovement(nothing);
|
||||||
|
// if(wizardStep==wizardChooseMode)
|
||||||
|
// {
|
||||||
|
// delete extraWidgets.at(0);
|
||||||
|
// delete extraWidgets.at(1);
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// }
|
||||||
|
// manualSettingsData=manualSettingsObj->getData();
|
||||||
|
// manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED;
|
||||||
|
// manualSettingsObj->setData(manualSettingsData);
|
||||||
|
// m_config->wzText->setText(tr("Welcome to the inputs configuration wizard.\n"
|
||||||
|
// "Please follow the instructions on the screen and only move your controls when asked to.\n"
|
||||||
|
// "Make sure you already configured your hardware settings on the proper tab and restarted your board.\n"
|
||||||
|
// "At any time you can press 'back' to return to the previous screeen or 'Cancel' to cancel the wizard.\n"));
|
||||||
|
// m_config->stackedWidget->setCurrentIndex(1);
|
||||||
|
// m_config->wzBack->setEnabled(false);
|
||||||
|
// wizardStep=wizardWelcome;
|
||||||
|
// }
|
||||||
|
// else if(step==wizardChooseMode)
|
||||||
|
// {
|
||||||
|
// m_config->graphicsView->setVisible(true);
|
||||||
|
// setTxMovement(nothing);
|
||||||
|
// if(wizardStep==wizardIdentifySticks)
|
||||||
|
// {
|
||||||
|
// disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls()));
|
||||||
|
// m_config->wzNext->setEnabled(true);
|
||||||
|
// }
|
||||||
|
// m_config->wzText->setText(tr("Please choose your transmiter type.\n"
|
||||||
|
// "Mode 1 means your throttle stick is on the right\n"
|
||||||
|
// "Mode 2 means your throttle stick is on the left\n"));
|
||||||
|
// m_config->wzBack->setEnabled(true);
|
||||||
|
// QRadioButton * mode1=new QRadioButton(tr("Mode 1"),this);
|
||||||
|
// QRadioButton * mode2=new QRadioButton(tr("Mode 2"),this);
|
||||||
|
// mode2->setChecked(true);
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// extraWidgets.append(mode1);
|
||||||
|
// extraWidgets.append(mode2);
|
||||||
|
// m_config->checkBoxesLayout->layout()->addWidget(mode1);
|
||||||
|
// m_config->checkBoxesLayout->layout()->addWidget(mode2);
|
||||||
|
// wizardStep=wizardChooseMode;
|
||||||
|
// }
|
||||||
|
// else if(step==wizardChooseType)
|
||||||
|
// {
|
||||||
|
// if(wizardStep==wizardChooseMode)
|
||||||
|
// {
|
||||||
|
// QRadioButton * mode=qobject_cast<QRadioButton *>(extraWidgets.at(0));
|
||||||
|
// if(mode->isChecked())
|
||||||
|
// transmitterMode=mode1;
|
||||||
|
// else
|
||||||
|
// transmitterMode=mode2;
|
||||||
|
// delete extraWidgets.at(0);
|
||||||
|
// delete extraWidgets.at(1);
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// m_config->wzText->setText(tr("Please choose your transmiter mode.\n"
|
||||||
|
// "Acro means normal transmitter\n"
|
||||||
|
// "Heli means there is a collective pitch and throttle input\n"));
|
||||||
|
// m_config->wzBack->setEnabled(true);
|
||||||
|
// QRadioButton * typeAcro=new QRadioButton(tr("Acro"),this);
|
||||||
|
// QRadioButton * typeHeli=new QRadioButton(tr("Heli"),this);
|
||||||
|
// typeAcro->setChecked(true);
|
||||||
|
// typeHeli->setChecked(false);
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// extraWidgets.append(typeAcro);
|
||||||
|
// extraWidgets.append(typeHeli);
|
||||||
|
// m_config->checkBoxesLayout->layout()->addWidget(typeAcro);
|
||||||
|
// m_config->checkBoxesLayout->layout()->addWidget(typeHeli);
|
||||||
|
// wizardStep=wizardChooseType;
|
||||||
|
// } else if(step==wizardIdentifySticks && !isSimple) {
|
||||||
|
// usedChannels.clear();
|
||||||
|
// if(wizardStep==wizardChooseType)
|
||||||
|
// {
|
||||||
|
// qDebug() << "Chosing type";
|
||||||
|
// QRadioButton * type=qobject_cast<QRadioButton *>(extraWidgets.at(0));
|
||||||
|
// if(type->isChecked())
|
||||||
|
// transmitterType=acro;
|
||||||
|
// else
|
||||||
|
// transmitterType=heli;
|
||||||
|
// qDebug() << "Checked: " << type->isChecked() << " " << "type is" << transmitterType;
|
||||||
|
// delete extraWidgets.at(0);
|
||||||
|
// delete extraWidgets.at(1);
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// }
|
||||||
|
// wizardStep=wizardIdentifySticks;
|
||||||
|
// currentCommand=0;
|
||||||
|
// getChannelFromStep(currentCommand);
|
||||||
|
// manualSettingsData=manualSettingsObj->getData();
|
||||||
|
// connect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls()));
|
||||||
|
// m_config->wzNext->setEnabled(false);
|
||||||
|
// }
|
||||||
|
// else if(step==wizardIdentifyCenter || (isSimple && step==wizardIdentifySticks))
|
||||||
|
// {
|
||||||
|
// setTxMovement(centerAll);
|
||||||
|
// if(wizardStep==wizardIdentifySticks)
|
||||||
|
// disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls()));
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
|
||||||
|
// manualSettingsObj->setData(manualSettingsData);
|
||||||
|
// manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata());
|
||||||
|
// }
|
||||||
|
// wizardStep=wizardIdentifyCenter;
|
||||||
|
// m_config->wzText->setText(QString(tr("Please center all control controls and press next when ready (if your FlightMode switch has only two positions, leave it on either position)")));
|
||||||
|
// }
|
||||||
|
// else if(step==wizardIdentifyLimits)
|
||||||
|
// {
|
||||||
|
// dimOtherControls(false);
|
||||||
|
// setTxMovement(moveAll);
|
||||||
|
// if(wizardStep==wizardIdentifyCenter)
|
||||||
|
// {
|
||||||
|
// wizardStep=wizardIdentifyLimits;
|
||||||
|
// manualCommandData=manualCommandObj->getData();
|
||||||
|
// manualSettingsData=manualSettingsObj->getData();
|
||||||
|
// for(unsigned int i=0;i<ManualControlCommand::CHANNEL_NUMELEM;++i)
|
||||||
|
// {
|
||||||
|
// manualSettingsData.ChannelNeutral[i]=manualCommandData.Channel[i];
|
||||||
|
// }
|
||||||
|
// manualSettingsObj->setData(manualSettingsData);
|
||||||
|
// }
|
||||||
|
// if(wizardStep==wizardIdentifyInverted)
|
||||||
|
// {
|
||||||
|
// foreach(QWidget * wd,extraWidgets)
|
||||||
|
// {
|
||||||
|
// QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||||
|
// if(cb)
|
||||||
|
// {
|
||||||
|
// disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
// delete cb;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
// wizardStep=wizardIdentifyLimits;
|
||||||
|
// m_config->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions and press next when ready")));
|
||||||
|
// UAVObject::Metadata mdata= manualCommandObj->getMetadata();
|
||||||
|
// mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||||
|
// mdata.flightTelemetryUpdatePeriod = 150;
|
||||||
|
// manualCommandObj->setMetadata(mdata);
|
||||||
|
// manualSettingsData=manualSettingsObj->getData();
|
||||||
|
// for(uint i=0;i<ManualControlSettings::CHANNELMAX_NUMELEM;++i)
|
||||||
|
// {
|
||||||
|
// manualSettingsData.ChannelMin[i]=manualSettingsData.ChannelNeutral[i];
|
||||||
|
// manualSettingsData.ChannelMax[i]=manualSettingsData.ChannelNeutral[i];
|
||||||
|
// }
|
||||||
|
// connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
|
||||||
|
// }
|
||||||
|
// else if(step==wizardIdentifyInverted)
|
||||||
|
// {
|
||||||
|
// dimOtherControls(true);
|
||||||
|
// setTxMovement(nothing);
|
||||||
|
// if(wizardStep==wizardIdentifyLimits)
|
||||||
|
// {
|
||||||
|
// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
|
||||||
|
// manualSettingsObj->setData(manualSettingsData);
|
||||||
|
// }
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames())
|
||||||
|
// {
|
||||||
|
// if(!name.contains("Access") && !name.contains("Flight"))
|
||||||
|
// {
|
||||||
|
// QCheckBox * cb=new QCheckBox(name,this);
|
||||||
|
// extraWidgets.append(cb);
|
||||||
|
// m_config->checkBoxesLayout->layout()->addWidget(cb);
|
||||||
|
// connect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
// wizardStep=wizardIdentifyInverted;
|
||||||
|
// m_config->wzText->setText(QString(tr("Please check the picture below and check all the sticks which show an inverted movement and press next when ready")));
|
||||||
|
// }
|
||||||
|
// else if(step==wizardFinish)
|
||||||
|
// {
|
||||||
|
// foreach(QWidget * wd,extraWidgets)
|
||||||
|
// {
|
||||||
|
// QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||||
|
// if(cb)
|
||||||
|
// {
|
||||||
|
// disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls()));
|
||||||
|
// delete cb;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// wizardStep=wizardFinish;
|
||||||
|
// extraWidgets.clear();
|
||||||
|
// m_config->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture below mimics your sticks movement.\n"
|
||||||
|
// "This new settings aren't saved to the board yet, after pressing next you will go to the initial screen where you can do that.")));
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// else if(step==wizardFinish+1)
|
||||||
|
// {
|
||||||
|
// setTxMovement(nothing);
|
||||||
|
// manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata());
|
||||||
|
// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
|
||||||
|
// manualSettingsData=manualSettingsObj->getData();
|
||||||
|
// manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]=
|
||||||
|
// manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+
|
||||||
|
// ((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]-
|
||||||
|
// manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02);
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
// manualSettingsObj->setData(manualSettingsData);
|
||||||
|
// m_config->stackedWidget->setCurrentIndex(0);
|
||||||
|
// wizardStep=wizardWelcome;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the display to indicate which channel the person should move
|
||||||
|
*/
|
||||||
|
void ConfigInputWidget::setChannel(int newChan)
|
||||||
|
{
|
||||||
|
if(newChan == ManualControlSettings::CHANNELGROUPS_COLLECTIVE)
|
||||||
|
m_config->wzText->setText(QString(tr("Please enable throttle hold mode and move the collective pitch stick")));
|
||||||
|
else if (newChan == ManualControlSettings::CHANNELGROUPS_FLIGHTMODE)
|
||||||
|
m_config->wzText->setText(QString(tr("Please flick the flight mode switch. For switches you may have to repeat this rapidly.")));
|
||||||
|
else
|
||||||
|
m_config->wzText->setText(QString(tr("Please move each control once at a time according to the instructions and picture below.\n\n"
|
||||||
|
"Move the %1 stick")).arg(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan)));
|
||||||
|
|
||||||
|
if(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan).contains("Accessory"))
|
||||||
|
m_config->wzNext->setEnabled(true);
|
||||||
|
|
||||||
|
setMoveFromCommand(newChan);
|
||||||
|
|
||||||
|
currentChannelNum = newChan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfortunately order of channel should be different in different conditions. Selects
|
||||||
|
* next channel based on heli or acro mode
|
||||||
|
*/
|
||||||
|
void ConfigInputWidget::nextChannel()
|
||||||
|
{
|
||||||
|
QList <int> order = (transmitterType == heli) ? heliChannelOrder : acroChannelOrder;
|
||||||
|
|
||||||
|
if(currentChannelNum == -1) {
|
||||||
|
setChannel(order[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < order.length() - 1; i++) {
|
||||||
|
if(order[i] == currentChannelNum) {
|
||||||
|
setChannel(order[i+1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentChannelNum = -1; // hit end of list
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfortunately order of channel should be different in different conditions. Selects
|
||||||
|
* previous channel based on heli or acro mode
|
||||||
|
*/
|
||||||
|
void ConfigInputWidget::prevChannel()
|
||||||
|
{
|
||||||
|
QList <int> order = transmitterType == heli ? heliChannelOrder : acroChannelOrder;
|
||||||
|
|
||||||
|
// No previous from unset channel or next state
|
||||||
|
if(currentChannelNum == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 1; i < order.length(); i++) {
|
||||||
|
if(order[i] == currentChannelNum) {
|
||||||
|
setChannel(order[i-1]);
|
||||||
|
usedChannels.removeLast();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentChannelNum = -1; // hit end of list
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::identifyControls()
|
||||||
|
{
|
||||||
|
static int debounce=0;
|
||||||
|
|
||||||
|
receiverActivityData=receiverActivityObj->getData();
|
||||||
|
if(receiverActivityData.ActiveChannel==255)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
receiverActivityData=receiverActivityObj->getData();
|
||||||
|
currentChannel.group=receiverActivityData.ActiveGroup;
|
||||||
|
currentChannel.number=receiverActivityData.ActiveChannel;
|
||||||
|
if(currentChannel==lastChannel)
|
||||||
|
++debounce;
|
||||||
|
lastChannel.group= currentChannel.group;
|
||||||
|
lastChannel.number=currentChannel.number;
|
||||||
|
if(!usedChannels.contains(lastChannel) && debounce>1)
|
||||||
|
{
|
||||||
|
debounce=0;
|
||||||
|
usedChannels.append(lastChannel);
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
manualSettingsData.ChannelGroups[currentChannelNum]=currentChannel.group;
|
||||||
|
manualSettingsData.ChannelNumber[currentChannelNum]=currentChannel.number;
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_config->wzText->clear();
|
||||||
|
setTxMovement(nothing);
|
||||||
|
|
||||||
|
QTimer::singleShot(300, this, SLOT(wzNext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::identifyLimits()
|
||||||
|
{
|
||||||
|
manualCommandData=manualCommandObj->getData();
|
||||||
|
for(uint i=0;i<ManualControlSettings::CHANNELMAX_NUMELEM;++i)
|
||||||
|
{
|
||||||
|
if(manualSettingsData.ChannelMin[i]>manualCommandData.Channel[i])
|
||||||
|
manualSettingsData.ChannelMin[i]=manualCommandData.Channel[i];
|
||||||
|
if(manualSettingsData.ChannelMax[i]<manualCommandData.Channel[i])
|
||||||
|
manualSettingsData.ChannelMax[i]=manualCommandData.Channel[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void ConfigInputWidget::setMoveFromCommand(int command)
|
||||||
|
{
|
||||||
|
//CHANNELNUMBER_ROLL=0, CHANNELNUMBER_PITCH=1, CHANNELNUMBER_YAW=2, CHANNELNUMBER_THROTTLE=3, CHANNELNUMBER_FLIGHTMODE=4, CHANNELNUMBER_ACCESSORY0=5, CHANNELNUMBER_ACCESSORY1=6, CHANNELNUMBER_ACCESSORY2=7 } ChannelNumberElem;
|
||||||
|
if(command==ManualControlSettings::CHANNELNUMBER_ROLL)
|
||||||
|
{
|
||||||
|
setTxMovement(moveRightHorizontalStick);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_PITCH)
|
||||||
|
{
|
||||||
|
if(transmitterMode==mode2)
|
||||||
|
setTxMovement(moveRightVerticalStick);
|
||||||
|
else
|
||||||
|
setTxMovement(moveLeftVerticalStick);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_YAW)
|
||||||
|
{
|
||||||
|
setTxMovement(moveLeftHorizontalStick);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_THROTTLE)
|
||||||
|
{
|
||||||
|
if(transmitterMode==mode2)
|
||||||
|
setTxMovement(moveLeftVerticalStick);
|
||||||
|
else
|
||||||
|
setTxMovement(moveRightVerticalStick);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_COLLECTIVE)
|
||||||
|
{
|
||||||
|
if(transmitterMode==mode2)
|
||||||
|
setTxMovement(moveLeftVerticalStick);
|
||||||
|
else
|
||||||
|
setTxMovement(moveRightVerticalStick);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_FLIGHTMODE)
|
||||||
|
{
|
||||||
|
setTxMovement(moveFlightMode);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_ACCESSORY0)
|
||||||
|
{
|
||||||
|
setTxMovement(moveAccess0);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_ACCESSORY1)
|
||||||
|
{
|
||||||
|
setTxMovement(moveAccess1);
|
||||||
|
}
|
||||||
|
else if(command==ManualControlSettings::CHANNELNUMBER_ACCESSORY2)
|
||||||
|
{
|
||||||
|
setTxMovement(moveAccess2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::setTxMovement(txMovements movement)
|
||||||
|
{
|
||||||
|
resetTxControls();
|
||||||
|
switch(movement)
|
||||||
|
{
|
||||||
|
case moveLeftVerticalStick:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveLeftVerticalStick;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveRightVerticalStick:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveRightVerticalStick;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveLeftHorizontalStick:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveLeftHorizontalStick;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveRightHorizontalStick:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveRightHorizontalStick;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveAccess0:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveAccess0;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveAccess1:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveAccess1;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveAccess2:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveAccess2;
|
||||||
|
animate->start(100);
|
||||||
|
break;
|
||||||
|
case moveFlightMode:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveFlightMode;
|
||||||
|
animate->start(1000);
|
||||||
|
break;
|
||||||
|
case centerAll:
|
||||||
|
movePos=0;
|
||||||
|
currentMovement=centerAll;
|
||||||
|
animate->start(1000);
|
||||||
|
break;
|
||||||
|
case moveAll:
|
||||||
|
movePos=0;
|
||||||
|
growing=true;
|
||||||
|
currentMovement=moveAll;
|
||||||
|
animate->start(50);
|
||||||
|
break;
|
||||||
|
case nothing:
|
||||||
|
movePos=0;
|
||||||
|
animate->stop();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::moveTxControls()
|
||||||
|
{
|
||||||
|
QTransform trans;
|
||||||
|
QGraphicsItem * item;
|
||||||
|
txMovementType move;
|
||||||
|
int limitMax;
|
||||||
|
int limitMin;
|
||||||
|
static bool auxFlag=false;
|
||||||
|
switch(currentMovement)
|
||||||
|
{
|
||||||
|
case moveLeftVerticalStick:
|
||||||
|
item=m_txLeftStick;
|
||||||
|
trans=m_txLeftStickOrig;
|
||||||
|
limitMax=STICK_MAX_MOVE;
|
||||||
|
limitMin=STICK_MIN_MOVE;
|
||||||
|
move=vertical;
|
||||||
|
break;
|
||||||
|
case moveRightVerticalStick:
|
||||||
|
item=m_txRightStick;
|
||||||
|
trans=m_txRightStickOrig;
|
||||||
|
limitMax=STICK_MAX_MOVE;
|
||||||
|
limitMin=STICK_MIN_MOVE;
|
||||||
|
move=vertical;
|
||||||
|
break;
|
||||||
|
case moveLeftHorizontalStick:
|
||||||
|
item=m_txLeftStick;
|
||||||
|
trans=m_txLeftStickOrig;
|
||||||
|
limitMax=STICK_MAX_MOVE;
|
||||||
|
limitMin=STICK_MIN_MOVE;
|
||||||
|
move=horizontal;
|
||||||
|
break;
|
||||||
|
case moveRightHorizontalStick:
|
||||||
|
item=m_txRightStick;
|
||||||
|
trans=m_txRightStickOrig;
|
||||||
|
limitMax=STICK_MAX_MOVE;
|
||||||
|
limitMin=STICK_MIN_MOVE;
|
||||||
|
move=horizontal;
|
||||||
|
break;
|
||||||
|
case moveAccess0:
|
||||||
|
item=m_txAccess0;
|
||||||
|
trans=m_txAccess0Orig;
|
||||||
|
limitMax=ACCESS_MAX_MOVE;
|
||||||
|
limitMin=ACCESS_MIN_MOVE;
|
||||||
|
move=horizontal;
|
||||||
|
break;
|
||||||
|
case moveAccess1:
|
||||||
|
item=m_txAccess1;
|
||||||
|
trans=m_txAccess1Orig;
|
||||||
|
limitMax=ACCESS_MAX_MOVE;
|
||||||
|
limitMin=ACCESS_MIN_MOVE;
|
||||||
|
move=horizontal;
|
||||||
|
break;
|
||||||
|
case moveAccess2:
|
||||||
|
item=m_txAccess2;
|
||||||
|
trans=m_txAccess2Orig;
|
||||||
|
limitMax=ACCESS_MAX_MOVE;
|
||||||
|
limitMin=ACCESS_MIN_MOVE;
|
||||||
|
move=horizontal;
|
||||||
|
break;
|
||||||
|
case moveFlightMode:
|
||||||
|
item=m_txFlightMode;
|
||||||
|
move=jump;
|
||||||
|
break;
|
||||||
|
case centerAll:
|
||||||
|
item=m_txArrows;
|
||||||
|
move=jump;
|
||||||
|
break;
|
||||||
|
case moveAll:
|
||||||
|
limitMax=STICK_MAX_MOVE;
|
||||||
|
limitMin=STICK_MIN_MOVE;
|
||||||
|
move=mix;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(move==vertical)
|
||||||
|
item->setTransform(trans.translate(0,movePos*10),false);
|
||||||
|
else if(move==horizontal)
|
||||||
|
item->setTransform(trans.translate(movePos*10,0),false);
|
||||||
|
else if(move==jump)
|
||||||
|
{
|
||||||
|
if(item==m_txArrows)
|
||||||
|
{
|
||||||
|
m_txArrows->setVisible(!m_txArrows->isVisible());
|
||||||
|
}
|
||||||
|
else if(item==m_txFlightMode)
|
||||||
|
{
|
||||||
|
QGraphicsSvgItem * svg;
|
||||||
|
svg=(QGraphicsSvgItem *)item;
|
||||||
|
if (svg)
|
||||||
|
{
|
||||||
|
if(svg->elementId()=="flightModeCenter")
|
||||||
|
{
|
||||||
|
if(growing)
|
||||||
|
{
|
||||||
|
svg->setElementId("flightModeRight");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeROrig,false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
svg->setElementId("flightModeLeft");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeLOrig,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(svg->elementId()=="flightModeRight")
|
||||||
|
{
|
||||||
|
growing=false;
|
||||||
|
svg->setElementId("flightModeCenter");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeCOrig,false);
|
||||||
|
}
|
||||||
|
else if(svg->elementId()=="flightModeLeft")
|
||||||
|
{
|
||||||
|
growing=true;
|
||||||
|
svg->setElementId("flightModeCenter");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeCOrig,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(move==mix)
|
||||||
|
{
|
||||||
|
trans=m_txAccess0Orig;
|
||||||
|
m_txAccess0->setTransform(trans.translate(movePos*10*ACCESS_MAX_MOVE/STICK_MAX_MOVE,0),false);
|
||||||
|
trans=m_txAccess1Orig;
|
||||||
|
m_txAccess1->setTransform(trans.translate(movePos*10*ACCESS_MAX_MOVE/STICK_MAX_MOVE,0),false);
|
||||||
|
trans=m_txAccess2Orig;
|
||||||
|
m_txAccess2->setTransform(trans.translate(movePos*10*ACCESS_MAX_MOVE/STICK_MAX_MOVE,0),false);
|
||||||
|
|
||||||
|
if(auxFlag)
|
||||||
|
{
|
||||||
|
trans=m_txLeftStickOrig;
|
||||||
|
m_txLeftStick->setTransform(trans.translate(0,movePos*10),false);
|
||||||
|
trans=m_txRightStickOrig;
|
||||||
|
m_txRightStick->setTransform(trans.translate(0,movePos*10),false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trans=m_txLeftStickOrig;
|
||||||
|
m_txLeftStick->setTransform(trans.translate(movePos*10,0),false);
|
||||||
|
trans=m_txRightStickOrig;
|
||||||
|
m_txRightStick->setTransform(trans.translate(movePos*10,0),false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(movePos==0)
|
||||||
|
{
|
||||||
|
m_txFlightMode->setElementId("flightModeCenter");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeCOrig,false);
|
||||||
|
}
|
||||||
|
else if(movePos==ACCESS_MAX_MOVE/2)
|
||||||
|
{
|
||||||
|
m_txFlightMode->setElementId("flightModeRight");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeROrig,false);
|
||||||
|
}
|
||||||
|
else if(movePos==ACCESS_MIN_MOVE/2)
|
||||||
|
{
|
||||||
|
m_txFlightMode->setElementId("flightModeLeft");
|
||||||
|
m_txFlightMode->setTransform(m_txFlightModeLOrig,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(move==horizontal || move==vertical ||move==mix)
|
||||||
|
{
|
||||||
|
if(movePos==0 && growing)
|
||||||
|
auxFlag=!auxFlag;
|
||||||
|
if(growing)
|
||||||
|
++movePos;
|
||||||
|
else
|
||||||
|
--movePos;
|
||||||
|
if(movePos>limitMax)
|
||||||
|
{
|
||||||
|
movePos=movePos-2;
|
||||||
|
growing=false;
|
||||||
|
}
|
||||||
|
if(movePos<limitMin)
|
||||||
|
{
|
||||||
|
movePos=movePos+2;
|
||||||
|
growing=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::moveSticks()
|
||||||
|
{
|
||||||
|
QTransform trans;
|
||||||
|
manualCommandData=manualCommandObj->getData();
|
||||||
|
if(transmitterMode==mode2)
|
||||||
|
{
|
||||||
|
trans=m_txLeftStickOrig;
|
||||||
|
m_txLeftStick->setTransform(trans.translate(manualCommandData.Yaw*STICK_MAX_MOVE*10,-manualCommandData.Throttle*STICK_MAX_MOVE*10),false);
|
||||||
|
trans=m_txRightStickOrig;
|
||||||
|
m_txRightStick->setTransform(trans.translate(manualCommandData.Roll*STICK_MAX_MOVE*10,manualCommandData.Pitch*STICK_MAX_MOVE*10),false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_config->ch0Cur->setToolTip("Channel neutral point");
|
trans=m_txRightStickOrig;
|
||||||
m_config->ch1Cur->setToolTip("Channel neutral point");
|
m_txRightStick->setTransform(trans.translate(manualCommandData.Roll*STICK_MAX_MOVE*10,-manualCommandData.Throttle*STICK_MAX_MOVE*10),false);
|
||||||
m_config->ch2Cur->setToolTip("Channel neutral point");
|
trans=m_txLeftStickOrig;
|
||||||
m_config->ch3Cur->setToolTip("Channel neutral point");
|
m_txLeftStick->setTransform(trans.translate(manualCommandData.Yaw*STICK_MAX_MOVE*10,manualCommandData.Pitch*STICK_MAX_MOVE*10),false);
|
||||||
m_config->ch4Cur->setToolTip("Channel neutral point");
|
}
|
||||||
m_config->ch5Cur->setToolTip("Channel neutral point");
|
}
|
||||||
m_config->ch6Cur->setToolTip("Channel neutral point");
|
|
||||||
m_config->ch7Cur->setToolTip("Channel neutral point");
|
void ConfigInputWidget::dimOtherControls(bool value)
|
||||||
|
{
|
||||||
|
qreal opac;
|
||||||
|
if(value)
|
||||||
|
opac=0.1;
|
||||||
|
else
|
||||||
|
opac=1;
|
||||||
|
m_txAccess0->setOpacity(opac);
|
||||||
|
m_txAccess1->setOpacity(opac);
|
||||||
|
m_txAccess2->setOpacity(opac);
|
||||||
|
m_txFlightMode->setOpacity(opac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::enableControls(bool enable)
|
||||||
|
{
|
||||||
|
m_config->configurationWizard->setEnabled(enable);
|
||||||
|
m_config->runCalibration->setEnabled(enable);
|
||||||
|
|
||||||
|
ConfigTaskWidget::enableControls(enable);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::invertControls()
|
||||||
|
{
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
foreach(QWidget * wd,extraWidgets)
|
||||||
|
{
|
||||||
|
QCheckBox * cb=qobject_cast<QCheckBox *>(wd);
|
||||||
|
if(cb)
|
||||||
|
{
|
||||||
|
int index=manualSettingsObj->getFields().at(0)->getElementNames().indexOf(cb->text());
|
||||||
|
if((cb->isChecked() && (manualSettingsData.ChannelMax[index]>manualSettingsData.ChannelMin[index])) ||
|
||||||
|
(!cb->isChecked() && (manualSettingsData.ChannelMax[index]<manualSettingsData.ChannelMin[index])))
|
||||||
|
{
|
||||||
|
qint16 aux;
|
||||||
|
aux=manualSettingsData.ChannelMax[index];
|
||||||
|
manualSettingsData.ChannelMax[index]=manualSettingsData.ChannelMin[index];
|
||||||
|
manualSettingsData.ChannelMin[index]=aux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
}
|
||||||
|
void ConfigInputWidget::moveFMSlider()
|
||||||
|
{
|
||||||
|
ManualControlSettings::DataFields manualSettingsDataPriv = manualSettingsObj->getData();
|
||||||
|
ManualControlCommand::DataFields manualCommandDataPriv=manualCommandObj->getData();
|
||||||
|
|
||||||
|
float valueScaled;
|
||||||
|
int chMin = manualSettingsDataPriv.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE];
|
||||||
|
int chMax = manualSettingsDataPriv.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE];
|
||||||
|
int chNeutral = manualSettingsDataPriv.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE];
|
||||||
|
|
||||||
|
int value = manualCommandDataPriv.Channel[ManualControlSettings::CHANNELMIN_FLIGHTMODE];
|
||||||
|
if ((chMax > chMin && value >= chNeutral) || (chMin > chMax && value <= chNeutral))
|
||||||
|
{
|
||||||
|
if (chMax != chNeutral)
|
||||||
|
valueScaled = (float)(value - chNeutral) / (float)(chMax - chNeutral);
|
||||||
|
else
|
||||||
|
valueScaled = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (chMin != chNeutral)
|
||||||
|
valueScaled = (float)(value - chNeutral) / (float)(chNeutral - chMin);
|
||||||
|
else
|
||||||
|
valueScaled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(valueScaled < -(1.0 / 3.0))
|
||||||
|
m_config->fmsSlider->setValue(-100);
|
||||||
|
else if (valueScaled > (1.0/3.0))
|
||||||
|
m_config->fmsSlider->setValue(100);
|
||||||
|
else
|
||||||
|
m_config->fmsSlider->setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::updateCalibration()
|
||||||
|
{
|
||||||
|
manualCommandData=manualCommandObj->getData();
|
||||||
|
for(uint i=0;i<ManualControlSettings::CHANNELMAX_NUMELEM;++i)
|
||||||
|
{
|
||||||
|
if((!reverse[i] && manualSettingsData.ChannelMin[i]>manualCommandData.Channel[i]) ||
|
||||||
|
(reverse[i] && manualSettingsData.ChannelMin[i]<manualCommandData.Channel[i]))
|
||||||
|
manualSettingsData.ChannelMin[i]=manualCommandData.Channel[i];
|
||||||
|
if((!reverse[i] && manualSettingsData.ChannelMax[i]<manualCommandData.Channel[i]) ||
|
||||||
|
(reverse[i] && manualSettingsData.ChannelMax[i]>manualCommandData.Channel[i]))
|
||||||
|
manualSettingsData.ChannelMax[i]=manualCommandData.Channel[i];
|
||||||
|
manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
manualSettingsObj->updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInputWidget::simpleCalibration(bool enable)
|
||||||
|
{
|
||||||
|
if (enable) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(tr("Arming Settings are now set to Always Disarmed for your safety."));
|
||||||
|
msgBox.setDetailedText(tr("You will have to reconfigure arming settings yourself afterwards."));
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
manualCommandData = manualCommandObj->getData();
|
||||||
|
|
||||||
|
manualSettingsData=manualSettingsObj->getData();
|
||||||
|
manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED;
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ManualControlCommand::CHANNEL_NUMELEM; i++) {
|
||||||
|
reverse[i] = manualSettingsData.ChannelMax[i] < manualSettingsData.ChannelMin[i];
|
||||||
|
manualSettingsData.ChannelMin[i] = manualCommandData.Channel[i];
|
||||||
|
manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i];
|
||||||
|
manualSettingsData.ChannelMax[i] = manualCommandData.Channel[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
fastMdata();
|
||||||
|
|
||||||
|
connect(manualCommandObj, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(updateCalibration()));
|
||||||
|
} else {
|
||||||
|
manualCommandData = manualCommandObj->getData();
|
||||||
|
manualSettingsData = manualSettingsObj->getData();
|
||||||
|
|
||||||
|
restoreMdata();
|
||||||
|
|
||||||
|
for (int i = 0; i < ManualControlCommand::CHANNEL_NUMELEM; i++)
|
||||||
|
manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i];
|
||||||
|
|
||||||
|
// Force flight mode neutral to middle
|
||||||
|
manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE] =
|
||||||
|
(manualSettingsData.ChannelMax[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE] +
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE]) / 2;
|
||||||
|
|
||||||
|
// Force throttle to be near min
|
||||||
|
manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]=
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+
|
||||||
|
((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]-
|
||||||
|
manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02);
|
||||||
|
|
||||||
|
manualSettingsObj->setData(manualSettingsData);
|
||||||
|
|
||||||
|
disconnect(manualCommandObj, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(updateCalibration()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,52 +34,125 @@
|
|||||||
#include "uavobject.h"
|
#include "uavobject.h"
|
||||||
#include <QtGui/QWidget>
|
#include <QtGui/QWidget>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include "inputchannelform.h"
|
||||||
|
#include "ui_inputchannelform.h"
|
||||||
|
#include <QRadioButton>
|
||||||
|
#include "manualcontrolcommand.h"
|
||||||
|
#include "manualcontrolsettings.h"
|
||||||
|
#include "receiveractivity.h"
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QtSvg/QSvgRenderer>
|
||||||
|
#include <QtSvg/QGraphicsSvgItem>
|
||||||
|
|
||||||
class Ui_InputWidget;
|
class Ui_InputWidget;
|
||||||
|
|
||||||
class ConfigInputWidget: public ConfigTaskWidget
|
class ConfigInputWidget: public ConfigTaskWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigInputWidget(QWidget *parent = 0);
|
ConfigInputWidget(QWidget *parent = 0);
|
||||||
~ConfigInputWidget();
|
~ConfigInputWidget();
|
||||||
|
enum wizardSteps{wizardWelcome,wizardChooseMode,wizardChooseType,wizardIdentifySticks,wizardIdentifyCenter,wizardIdentifyLimits,wizardIdentifyInverted,wizardFinish,wizardNone};
|
||||||
|
enum txMode{mode1,mode2};
|
||||||
|
enum txMovements{moveLeftVerticalStick,moveRightVerticalStick,moveLeftHorizontalStick,moveRightHorizontalStick,moveAccess0,moveAccess1,moveAccess2,moveFlightMode,centerAll,moveAll,nothing};
|
||||||
|
enum txMovementType{vertical,horizontal,jump,mix};
|
||||||
|
enum txType {acro, heli};
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool growing;
|
||||||
|
bool reverse[ManualControlSettings::CHANNELNEUTRAL_NUMELEM];
|
||||||
|
txMovements currentMovement;
|
||||||
|
int movePos;
|
||||||
|
void setTxMovement(txMovements movement);
|
||||||
Ui_InputWidget *m_config;
|
Ui_InputWidget *m_config;
|
||||||
|
wizardSteps wizardStep;
|
||||||
|
QList<QWidget*> extraWidgets;
|
||||||
|
txMode transmitterMode;
|
||||||
|
txType transmitterType;
|
||||||
|
struct channelsStruct
|
||||||
|
{
|
||||||
|
bool operator ==(const channelsStruct& rhs) const
|
||||||
|
{
|
||||||
|
return((group==rhs.group) &&(number==rhs.number));
|
||||||
|
}
|
||||||
|
int group;
|
||||||
|
int number;
|
||||||
|
}lastChannel;
|
||||||
|
channelsStruct currentChannel;
|
||||||
|
QList<channelsStruct> usedChannels;
|
||||||
|
QEventLoop * loop;
|
||||||
|
bool skipflag;
|
||||||
|
|
||||||
QList<QSlider> sliders;
|
int currentChannelNum;
|
||||||
|
QList<int> heliChannelOrder;
|
||||||
|
QList<int> acroChannelOrder;
|
||||||
|
|
||||||
void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, int value, bool reversed);
|
ManualControlCommand * manualCommandObj;
|
||||||
|
ManualControlCommand::DataFields manualCommandData;
|
||||||
|
UAVObject::Metadata manualControlMdata;
|
||||||
|
ManualControlSettings * manualSettingsObj;
|
||||||
|
ManualControlSettings::DataFields manualSettingsData;
|
||||||
|
ManualControlSettings::DataFields previousManualSettingsData;
|
||||||
|
ReceiverActivity * receiverActivityObj;
|
||||||
|
ReceiverActivity::DataFields receiverActivityData;
|
||||||
|
|
||||||
void assignChannel(UAVDataObject *obj, QString str);
|
QSvgRenderer *m_renderer;
|
||||||
void assignOutputChannel(UAVDataObject *obj, QString str);
|
|
||||||
|
|
||||||
int mccDataRate;
|
// Background: background
|
||||||
|
QGraphicsSvgItem *m_txMainBody;
|
||||||
|
QGraphicsSvgItem *m_txLeftStick;
|
||||||
|
QGraphicsSvgItem *m_txRightStick;
|
||||||
|
QGraphicsSvgItem *m_txAccess0;
|
||||||
|
QGraphicsSvgItem *m_txAccess1;
|
||||||
|
QGraphicsSvgItem *m_txAccess2;
|
||||||
|
QGraphicsSvgItem *m_txFlightMode;
|
||||||
|
QGraphicsSvgItem *m_txBackground;
|
||||||
|
QGraphicsSvgItem *m_txArrows;
|
||||||
|
QTransform m_txLeftStickOrig;
|
||||||
|
QTransform m_txRightStickOrig;
|
||||||
|
QTransform m_txAccess0Orig;
|
||||||
|
QTransform m_txAccess1Orig;
|
||||||
|
QTransform m_txAccess2Orig;
|
||||||
|
QTransform m_txFlightModeCOrig;
|
||||||
|
QTransform m_txFlightModeLOrig;
|
||||||
|
QTransform m_txFlightModeROrig;
|
||||||
|
QTransform m_txMainBodyOrig;
|
||||||
|
QTransform m_txArrowsOrig;
|
||||||
|
QTimer * animate;
|
||||||
|
void resetTxControls();
|
||||||
|
void setMoveFromCommand(int command);
|
||||||
|
|
||||||
UAVObject::Metadata accInitialData;
|
void fastMdata();
|
||||||
|
void restoreMdata();
|
||||||
|
|
||||||
QList<QSlider*> inSliders;
|
void setChannel(int);
|
||||||
QList<QLabel*> inMaxLabels;
|
void nextChannel();
|
||||||
QList<QLabel*> inMinLabels;
|
void prevChannel();
|
||||||
QList<QLabel*> inNeuLabels;
|
|
||||||
QList<QCheckBox*> inRevCheckboxes;
|
|
||||||
QList<QComboBox*> inChannelAssign;
|
|
||||||
|
|
||||||
bool firstUpdate;
|
void wizardSetUpStep(enum wizardSteps);
|
||||||
|
void wizardTearDownStep(enum wizardSteps);
|
||||||
virtual void enableControls(bool enable);
|
|
||||||
void receiverHelp();
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateChannels(UAVObject* obj);
|
void wzNext();
|
||||||
virtual void refreshValues();
|
void wzBack();
|
||||||
void sendRCInputUpdate();
|
void wzCancel();
|
||||||
void saveRCInputObject();
|
void goToWizard();
|
||||||
void reverseCheckboxClicked(bool state);
|
|
||||||
void openHelp();
|
void openHelp();
|
||||||
void updateTips(int);
|
void identifyControls();
|
||||||
|
void identifyLimits();
|
||||||
|
void moveTxControls();
|
||||||
|
void moveSticks();
|
||||||
|
void dimOtherControls(bool value);
|
||||||
|
void moveFMSlider();
|
||||||
|
void invertControls();
|
||||||
|
void simpleCalibration(bool state);
|
||||||
|
void updateCalibration();
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
virtual void enableControls(bool enable);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,7 +45,8 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
|
|||||||
m_config->setupUi(this);
|
m_config->setupUi(this);
|
||||||
|
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
setupButtons(m_config->saveRCOutputToRAM,m_config->saveRCOutputToSD);
|
||||||
|
addUAVObject("ActuatorSettings");
|
||||||
|
|
||||||
// First of all, put all the channel widgets into lists, so that we can
|
// First of all, put all the channel widgets into lists, so that we can
|
||||||
// manipulate those:
|
// manipulate those:
|
||||||
@ -106,10 +107,7 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
|
|||||||
<< m_config->ch7Link;
|
<< m_config->ch7Link;
|
||||||
|
|
||||||
// Register for ActuatorSettings changes:
|
// Register for ActuatorSettings changes:
|
||||||
UAVDataObject * obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
|
for (int i = 0; i < 8; i++) {
|
||||||
connect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(refreshValues()));
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
connect(outMin[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
|
connect(outMin[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
|
||||||
connect(outMax[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
|
connect(outMax[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
|
||||||
connect(reversals[i], SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool)));
|
connect(reversals[i], SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool)));
|
||||||
@ -124,13 +122,8 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
|
|||||||
for (int i = 0; i < links.count(); i++)
|
for (int i = 0; i < links.count(); i++)
|
||||||
connect(links[i], SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool)));
|
connect(links[i], SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool)));
|
||||||
|
|
||||||
connect(m_config->saveRCOutputToSD, SIGNAL(clicked()), this, SLOT(saveRCOutputObject()));
|
|
||||||
connect(m_config->saveRCOutputToRAM, SIGNAL(clicked()), this, SLOT(sendRCOutputUpdate()));
|
|
||||||
|
|
||||||
enableControls(false);
|
refreshWidgetsValues();
|
||||||
refreshValues();
|
|
||||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect()));
|
|
||||||
connect(parent, SIGNAL(autopilotDisconnected()), this, SLOT(onAutopilotDisconnect()));
|
|
||||||
|
|
||||||
firstUpdate = true;
|
firstUpdate = true;
|
||||||
|
|
||||||
@ -138,6 +131,43 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
|
|||||||
|
|
||||||
// Connect the help button
|
// Connect the help button
|
||||||
connect(m_config->outputHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
connect(m_config->outputHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
|
addWidget(m_config->outputRate3);
|
||||||
|
addWidget(m_config->outputRate2);
|
||||||
|
addWidget(m_config->outputRate1);
|
||||||
|
addWidget(m_config->ch0OutMin);
|
||||||
|
addWidget(m_config->ch0OutSlider);
|
||||||
|
addWidget(m_config->ch0OutMax);
|
||||||
|
addWidget(m_config->ch0Rev);
|
||||||
|
addWidget(m_config->ch0Link);
|
||||||
|
addWidget(m_config->ch1OutMin);
|
||||||
|
addWidget(m_config->ch1OutSlider);
|
||||||
|
addWidget(m_config->ch1OutMax);
|
||||||
|
addWidget(m_config->ch1Rev);
|
||||||
|
addWidget(m_config->ch2OutMin);
|
||||||
|
addWidget(m_config->ch2OutSlider);
|
||||||
|
addWidget(m_config->ch2OutMax);
|
||||||
|
addWidget(m_config->ch2Rev);
|
||||||
|
addWidget(m_config->ch3OutMin);
|
||||||
|
addWidget(m_config->ch3OutSlider);
|
||||||
|
addWidget(m_config->ch3OutMax);
|
||||||
|
addWidget(m_config->ch3Rev);
|
||||||
|
addWidget(m_config->ch4OutMin);
|
||||||
|
addWidget(m_config->ch4OutSlider);
|
||||||
|
addWidget(m_config->ch4OutMax);
|
||||||
|
addWidget(m_config->ch4Rev);
|
||||||
|
addWidget(m_config->ch5OutMin);
|
||||||
|
addWidget(m_config->ch5OutSlider);
|
||||||
|
addWidget(m_config->ch5OutMax);
|
||||||
|
addWidget(m_config->ch5Rev);
|
||||||
|
addWidget(m_config->ch6OutMin);
|
||||||
|
addWidget(m_config->ch6OutSlider);
|
||||||
|
addWidget(m_config->ch6OutMax);
|
||||||
|
addWidget(m_config->ch6Rev);
|
||||||
|
addWidget(m_config->ch7OutMin);
|
||||||
|
addWidget(m_config->ch7OutSlider);
|
||||||
|
addWidget(m_config->ch7OutMax);
|
||||||
|
addWidget(m_config->ch7Rev);
|
||||||
|
addWidget(m_config->spinningArmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigOutputWidget::~ConfigOutputWidget()
|
ConfigOutputWidget::~ConfigOutputWidget()
|
||||||
@ -146,14 +176,6 @@ ConfigOutputWidget::~ConfigOutputWidget()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************
|
|
||||||
|
|
||||||
void ConfigOutputWidget::enableControls(bool enable)
|
|
||||||
{
|
|
||||||
m_config->saveRCOutputToSD->setEnabled(enable);
|
|
||||||
//m_config->saveRCOutputToRAM->setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************************************
|
// ************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,8 +377,9 @@ void ConfigOutputWidget::sendChannelTest(int value)
|
|||||||
/**
|
/**
|
||||||
Request the current config from the board (RC Output)
|
Request the current config from the board (RC Output)
|
||||||
*/
|
*/
|
||||||
void ConfigOutputWidget::refreshValues()
|
void ConfigOutputWidget::refreshWidgetsValues()
|
||||||
{
|
{
|
||||||
|
bool dirty=isDirty();
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
|
|
||||||
@ -444,14 +467,14 @@ void ConfigOutputWidget::refreshValues()
|
|||||||
outSliders[i]->setValue(value);
|
outSliders[i]->setValue(value);
|
||||||
outLabels[i]->setText(QString::number(value));
|
outLabels[i]->setText(QString::number(value));
|
||||||
}
|
}
|
||||||
|
setDirty(dirty);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the config to the board, without saving to the SD card (RC Output)
|
* Sends the config to the board, without saving to the SD card (RC Output)
|
||||||
*/
|
*/
|
||||||
void ConfigOutputWidget::sendRCOutputUpdate()
|
void ConfigOutputWidget::updateObjectsFromWidgets()
|
||||||
{
|
{
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
@ -479,27 +502,8 @@ void ConfigOutputWidget::sendRCOutputUpdate()
|
|||||||
field->setValue(m_config->outputRate2->value(),1);
|
field->setValue(m_config->outputRate2->value(),1);
|
||||||
field->setValue(m_config->outputRate3->value(),2);
|
field->setValue(m_config->outputRate3->value(),2);
|
||||||
field->setValue(m_config->outputRate4->value(),3);
|
field->setValue(m_config->outputRate4->value(),3);
|
||||||
|
|
||||||
// ... and send to the OP Board
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sends the config to the board and request saving into the SD card (RC Output)
|
|
||||||
*/
|
|
||||||
void ConfigOutputWidget::saveRCOutputObject()
|
|
||||||
{
|
|
||||||
// Send update so that the latest value is saved
|
|
||||||
sendRCOutputUpdate();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
saveObjectToSD(obj);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the minimum/maximum value of the channel 0 to seven output sliders.
|
Sets the minimum/maximum value of the channel 0 to seven output sliders.
|
||||||
Have to do it here because setMinimum is not a slot.
|
Have to do it here because setMinimum is not a slot.
|
||||||
|
@ -69,12 +69,10 @@ private:
|
|||||||
|
|
||||||
bool firstUpdate;
|
bool firstUpdate;
|
||||||
|
|
||||||
virtual void enableControls(bool enable);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
virtual void refreshValues();
|
virtual void refreshWidgetsValues();
|
||||||
void sendRCOutputUpdate();
|
void updateObjectsFromWidgets();
|
||||||
void saveRCOutputObject();
|
|
||||||
void runChannelTests(bool state);
|
void runChannelTests(bool state);
|
||||||
void sendChannelTest(int value);
|
void sendChannelTest(int value);
|
||||||
void setChOutRange();
|
void setChOutRange();
|
||||||
|
@ -43,21 +43,15 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
|||||||
m_stabilization->setupUi(this);
|
m_stabilization->setupUi(this);
|
||||||
|
|
||||||
|
|
||||||
connect(m_stabilization->saveStabilizationToSD, SIGNAL(clicked()), this, SLOT(saveStabilizationUpdate()));
|
setupButtons(m_stabilization->saveStabilizationToRAM,m_stabilization->saveStabilizationToSD);
|
||||||
connect(m_stabilization->saveStabilizationToRAM, SIGNAL(clicked()), this, SLOT(sendStabilizationUpdate()));
|
|
||||||
|
|
||||||
enableControls(false);
|
addUAVObject("StabilizationSettings");
|
||||||
refreshValues();
|
|
||||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect()));
|
|
||||||
connect(parent, SIGNAL(autopilotDisconnected()),this, SLOT(onAutopilotDisconnect()));
|
|
||||||
|
|
||||||
// Now connect the widget to the StabilizationSettings object
|
refreshWidgetsValues();
|
||||||
UAVObject *obj = getObjectManager()->getObject(QString("StabilizationSettings"));
|
|
||||||
connect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(refreshValues()));
|
|
||||||
|
|
||||||
// Create a timer to regularly send the object update in case
|
// Create a timer to regularly send the object update in case
|
||||||
// we want realtime updates.
|
// we want realtime updates.
|
||||||
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(sendStabilizationUpdate()));
|
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateObjectsFromWidgets()));
|
||||||
connect(m_stabilization->realTimeUpdates, SIGNAL(toggled(bool)), this, SLOT(realtimeUpdateToggle(bool)));
|
connect(m_stabilization->realTimeUpdates, SIGNAL(toggled(bool)), this, SLOT(realtimeUpdateToggle(bool)));
|
||||||
|
|
||||||
// Connect the updates of the stab values
|
// Connect the updates of the stab values
|
||||||
@ -79,6 +73,35 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
|||||||
|
|
||||||
// Connect the help button
|
// Connect the help button
|
||||||
connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
|
addWidget(m_stabilization->rateRollKp);
|
||||||
|
addWidget(m_stabilization->rateRollKi);
|
||||||
|
addWidget(m_stabilization->rateRollILimit);
|
||||||
|
addWidget(m_stabilization->ratePitchKp);
|
||||||
|
addWidget(m_stabilization->ratePitchKi);
|
||||||
|
addWidget(m_stabilization->ratePitchILimit);
|
||||||
|
addWidget(m_stabilization->rateYawKp);
|
||||||
|
addWidget(m_stabilization->rateYawKi);
|
||||||
|
addWidget(m_stabilization->rateYawILimit);
|
||||||
|
addWidget(m_stabilization->rollKp);
|
||||||
|
addWidget(m_stabilization->rollKi);
|
||||||
|
addWidget(m_stabilization->rollILimit);
|
||||||
|
addWidget(m_stabilization->yawILimit);
|
||||||
|
addWidget(m_stabilization->yawKi);
|
||||||
|
addWidget(m_stabilization->yawKp);
|
||||||
|
addWidget(m_stabilization->pitchKp);
|
||||||
|
addWidget(m_stabilization->pitchKi);
|
||||||
|
addWidget(m_stabilization->pitchILimit);
|
||||||
|
addWidget(m_stabilization->rollMax);
|
||||||
|
addWidget(m_stabilization->pitchMax);
|
||||||
|
addWidget(m_stabilization->yawMax);
|
||||||
|
addWidget(m_stabilization->manualRoll);
|
||||||
|
addWidget(m_stabilization->manualPitch);
|
||||||
|
addWidget(m_stabilization->manualYaw);
|
||||||
|
addWidget(m_stabilization->maximumRoll);
|
||||||
|
addWidget(m_stabilization->maximumPitch);
|
||||||
|
addWidget(m_stabilization->maximumYaw);
|
||||||
|
addWidget(m_stabilization->lowThrottleZeroIntegral);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigStabilizationWidget::~ConfigStabilizationWidget()
|
ConfigStabilizationWidget::~ConfigStabilizationWidget()
|
||||||
@ -86,13 +109,6 @@ ConfigStabilizationWidget::~ConfigStabilizationWidget()
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConfigStabilizationWidget::enableControls(bool enable)
|
|
||||||
{
|
|
||||||
//m_stabilization->saveStabilizationToRAM->setEnabled(enable);
|
|
||||||
m_stabilization->saveStabilizationToSD->setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigStabilizationWidget::updateRateRollKP(double val)
|
void ConfigStabilizationWidget::updateRateRollKP(double val)
|
||||||
{
|
{
|
||||||
if (m_stabilization->linkRateRP->isChecked()) {
|
if (m_stabilization->linkRateRP->isChecked()) {
|
||||||
@ -187,8 +203,9 @@ void ConfigStabilizationWidget::updatePitchILimit(double val)
|
|||||||
/**
|
/**
|
||||||
Request stabilization settings from the board
|
Request stabilization settings from the board
|
||||||
*/
|
*/
|
||||||
void ConfigStabilizationWidget::refreshValues()
|
void ConfigStabilizationWidget::refreshWidgetsValues()
|
||||||
{
|
{
|
||||||
|
bool dirty=isDirty();
|
||||||
// Not needed anymore as this slot is only called whenever we get
|
// Not needed anymore as this slot is only called whenever we get
|
||||||
// a signal that the object was just updated
|
// a signal that the object was just updated
|
||||||
// stabSettings->requestUpdate();
|
// stabSettings->requestUpdate();
|
||||||
@ -229,9 +246,9 @@ void ConfigStabilizationWidget::refreshValues()
|
|||||||
m_stabilization->maximumRoll->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_ROLL]);
|
m_stabilization->maximumRoll->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_ROLL]);
|
||||||
m_stabilization->maximumPitch->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH]);
|
m_stabilization->maximumPitch->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH]);
|
||||||
m_stabilization->maximumYaw->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW]);
|
m_stabilization->maximumYaw->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW]);
|
||||||
|
m_stabilization->lowThrottleZeroIntegral->setChecked(stabData.LowThrottleZeroIntegral==StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE ? true : false);
|
||||||
|
|
||||||
m_stabilization->lowThrottleZeroIntegral->setChecked(
|
setDirty(dirty);
|
||||||
stabData.LowThrottleZeroIntegral == StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,7 +256,7 @@ void ConfigStabilizationWidget::refreshValues()
|
|||||||
Send telemetry settings to the board
|
Send telemetry settings to the board
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ConfigStabilizationWidget::sendStabilizationUpdate()
|
void ConfigStabilizationWidget::updateObjectsFromWidgets()
|
||||||
{
|
{
|
||||||
StabilizationSettings::DataFields stabData = stabSettings->getData();
|
StabilizationSettings::DataFields stabData = stabSettings->getData();
|
||||||
|
|
||||||
@ -279,28 +296,12 @@ void ConfigStabilizationWidget::sendStabilizationUpdate()
|
|||||||
stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH] = m_stabilization->maximumPitch->value();
|
stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH] = m_stabilization->maximumPitch->value();
|
||||||
stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW] = m_stabilization->maximumYaw->value();
|
stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW] = m_stabilization->maximumYaw->value();
|
||||||
|
|
||||||
stabData.LowThrottleZeroIntegral = m_stabilization->lowThrottleZeroIntegral->isChecked() ?
|
stabData.LowThrottleZeroIntegral = (m_stabilization->lowThrottleZeroIntegral->isChecked() ? StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE :StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_FALSE);
|
||||||
StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE :
|
|
||||||
StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_FALSE;
|
|
||||||
|
|
||||||
stabSettings->setData(stabData); // this is atomic
|
stabSettings->setData(stabData); // this is atomic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Send telemetry settings to the board and request saving to SD card
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ConfigStabilizationWidget::saveStabilizationUpdate()
|
|
||||||
{
|
|
||||||
// Send update so that the latest value is saved
|
|
||||||
sendStabilizationUpdate();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("StabilizationSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
saveObjectToSD(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ConfigStabilizationWidget::realtimeUpdateToggle(bool state)
|
void ConfigStabilizationWidget::realtimeUpdateToggle(bool state)
|
||||||
{
|
{
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -49,12 +49,10 @@ private:
|
|||||||
Ui_StabilizationWidget *m_stabilization;
|
Ui_StabilizationWidget *m_stabilization;
|
||||||
StabilizationSettings* stabSettings;
|
StabilizationSettings* stabSettings;
|
||||||
QTimer updateTimer;
|
QTimer updateTimer;
|
||||||
virtual void enableControls(bool enable);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
virtual void refreshValues();
|
virtual void refreshWidgetsValues();
|
||||||
void sendStabilizationUpdate();
|
void updateObjectsFromWidgets();
|
||||||
void saveStabilizationUpdate();
|
|
||||||
void realtimeUpdateToggle(bool);
|
void realtimeUpdateToggle(bool);
|
||||||
void openHelp();
|
void openHelp();
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include <QtGui/QWidget>
|
#include <QtGui/QWidget>
|
||||||
|
|
||||||
|
|
||||||
ConfigTaskWidget::ConfigTaskWidget(QWidget *parent) : QWidget(parent),smartsave(NULL),dirty(false)
|
ConfigTaskWidget::ConfigTaskWidget(QWidget *parent) : QWidget(parent),isConnected(false),smartsave(NULL),dirty(false)
|
||||||
{
|
{
|
||||||
pm = ExtensionSystem::PluginManager::instance();
|
pm = ExtensionSystem::PluginManager::instance();
|
||||||
objManager = pm->getObject<UAVObjectManager>();
|
objManager = pm->getObject<UAVObjectManager>();
|
||||||
@ -43,13 +43,27 @@ void ConfigTaskWidget::addUAVObject(QString objectName)
|
|||||||
{
|
{
|
||||||
addUAVObjectToWidgetRelation(objectName,"",NULL);
|
addUAVObjectToWidgetRelation(objectName,"",NULL);
|
||||||
}
|
}
|
||||||
void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString field, QWidget * widget)
|
void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString field, QWidget * widget, QString index)
|
||||||
|
{
|
||||||
|
UAVObject *obj=NULL;
|
||||||
|
UAVObjectField *_field=NULL;
|
||||||
|
obj = objManager->getObject(QString(object));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
_field = obj->getField(QString(field));
|
||||||
|
Q_ASSERT(_field);
|
||||||
|
addUAVObjectToWidgetRelation(object,field,widget,_field->getElementNames().indexOf(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString field, QWidget * widget, int index,int scale)
|
||||||
{
|
{
|
||||||
UAVObject *obj=NULL;
|
UAVObject *obj=NULL;
|
||||||
UAVObjectField *_field=NULL;
|
UAVObjectField *_field=NULL;
|
||||||
if(!object.isEmpty())
|
if(!object.isEmpty())
|
||||||
|
{
|
||||||
obj = objManager->getObject(QString(object));
|
obj = objManager->getObject(QString(object));
|
||||||
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues()));
|
Q_ASSERT(obj);
|
||||||
|
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues()));
|
||||||
|
}
|
||||||
//smartsave->addObject(obj);
|
//smartsave->addObject(obj);
|
||||||
if(!field.isEmpty() && obj)
|
if(!field.isEmpty() && obj)
|
||||||
_field = obj->getField(QString(field));
|
_field = obj->getField(QString(field));
|
||||||
@ -57,9 +71,11 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel
|
|||||||
ow->field=_field;
|
ow->field=_field;
|
||||||
ow->object=obj;
|
ow->object=obj;
|
||||||
ow->widget=widget;
|
ow->widget=widget;
|
||||||
|
ow->index=index;
|
||||||
|
ow->scale=scale;
|
||||||
objOfInterest.append(ow);
|
objOfInterest.append(ow);
|
||||||
if(obj)
|
if(obj)
|
||||||
smartsave->addObject(obj);
|
smartsave->addObject((UAVDataObject*)obj);
|
||||||
if(widget==NULL)
|
if(widget==NULL)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
@ -88,6 +104,15 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel
|
|||||||
{
|
{
|
||||||
connect(cb,SIGNAL(valueChanged(double)),this,SLOT(widgetsContentsChanged()));
|
connect(cb,SIGNAL(valueChanged(double)),this,SLOT(widgetsContentsChanged()));
|
||||||
}
|
}
|
||||||
|
else if(QCheckBox * cb=qobject_cast<QCheckBox *>(widget))
|
||||||
|
{
|
||||||
|
connect(cb,SIGNAL(clicked()),this,SLOT(widgetsContentsChanged()));
|
||||||
|
}
|
||||||
|
else if(QPushButton * cb=qobject_cast<QPushButton *>(widget))
|
||||||
|
{
|
||||||
|
connect(cb,SIGNAL(clicked()),this,SLOT(widgetsContentsChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,17 +151,21 @@ double ConfigTaskWidget::listMean(QList<double> list)
|
|||||||
|
|
||||||
void ConfigTaskWidget::onAutopilotDisconnect()
|
void ConfigTaskWidget::onAutopilotDisconnect()
|
||||||
{
|
{
|
||||||
enableControls(false);
|
isConnected=false;
|
||||||
|
enableControls(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::onAutopilotConnect()
|
void ConfigTaskWidget::onAutopilotConnect()
|
||||||
{
|
{
|
||||||
enableControls(true);
|
dirty=false;
|
||||||
refreshWidgetsValues();
|
isConnected=true;
|
||||||
|
enableControls(true);
|
||||||
|
refreshWidgetsValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::populateWidgets()
|
void ConfigTaskWidget::populateWidgets()
|
||||||
{
|
{
|
||||||
|
bool dirtyBack=dirty;
|
||||||
foreach(objectToWidget * ow,objOfInterest)
|
foreach(objectToWidget * ow,objOfInterest)
|
||||||
{
|
{
|
||||||
if(ow->object==NULL || ow->field==NULL)
|
if(ow->object==NULL || ow->field==NULL)
|
||||||
@ -146,18 +175,27 @@ void ConfigTaskWidget::populateWidgets()
|
|||||||
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
||||||
{
|
{
|
||||||
cb->addItems(ow->field->getOptions());
|
cb->addItems(ow->field->getOptions());
|
||||||
cb->setCurrentIndex(cb->findText(ow->field->getValue().toString()));
|
cb->setCurrentIndex(cb->findText(ow->field->getValue(ow->index).toString()));
|
||||||
}
|
}
|
||||||
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
||||||
{
|
{
|
||||||
cb->setText(ow->field->getValue().toString());
|
cb->setText(ow->field->getValue(ow->index).toString());
|
||||||
|
}
|
||||||
|
else if(QSpinBox * cb=qobject_cast<QSpinBox *>(ow->widget))
|
||||||
|
{
|
||||||
|
cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale);
|
||||||
|
}
|
||||||
|
else if(QSlider * cb=qobject_cast<QSlider *>(ow->widget))
|
||||||
|
{
|
||||||
|
cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dirty=false;
|
setDirty(dirtyBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::refreshWidgetsValues()
|
void ConfigTaskWidget::refreshWidgetsValues()
|
||||||
{
|
{
|
||||||
|
bool dirtyBack=dirty;
|
||||||
foreach(objectToWidget * ow,objOfInterest)
|
foreach(objectToWidget * ow,objOfInterest)
|
||||||
{
|
{
|
||||||
if(ow->object==NULL || ow->field==NULL)
|
if(ow->object==NULL || ow->field==NULL)
|
||||||
@ -166,13 +204,22 @@ void ConfigTaskWidget::refreshWidgetsValues()
|
|||||||
}
|
}
|
||||||
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
||||||
{
|
{
|
||||||
cb->setCurrentIndex(cb->findText(ow->field->getValue().toString()));
|
cb->setCurrentIndex(cb->findText(ow->field->getValue(ow->index).toString()));
|
||||||
}
|
}
|
||||||
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
||||||
{
|
{
|
||||||
cb->setText(ow->field->getValue().toString());
|
cb->setText(ow->field->getValue(ow->index).toString());
|
||||||
|
}
|
||||||
|
else if(QSpinBox * cb=qobject_cast<QSpinBox *>(ow->widget))
|
||||||
|
{
|
||||||
|
cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale);
|
||||||
|
}
|
||||||
|
else if(QSlider * cb=qobject_cast<QSlider *>(ow->widget))
|
||||||
|
{
|
||||||
|
cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setDirty(dirtyBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::updateObjectsFromWidgets()
|
void ConfigTaskWidget::updateObjectsFromWidgets()
|
||||||
@ -185,11 +232,19 @@ void ConfigTaskWidget::updateObjectsFromWidgets()
|
|||||||
}
|
}
|
||||||
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
else if(QComboBox * cb=qobject_cast<QComboBox *>(ow->widget))
|
||||||
{
|
{
|
||||||
ow->field->setValue(cb->currentText());
|
ow->field->setValue(cb->currentText(),ow->index);
|
||||||
}
|
}
|
||||||
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
else if(QLabel * cb=qobject_cast<QLabel *>(ow->widget))
|
||||||
{
|
{
|
||||||
ow->field->setValue(cb->text());
|
ow->field->setValue(cb->text(),ow->index);
|
||||||
|
}
|
||||||
|
else if(QSpinBox * cb=qobject_cast<QSpinBox *>(ow->widget))
|
||||||
|
{
|
||||||
|
ow->field->setValue(cb->value()* ow->scale,ow->index);
|
||||||
|
}
|
||||||
|
else if(QSlider * cb=qobject_cast<QSlider *>(ow->widget))
|
||||||
|
{
|
||||||
|
ow->field->setValue(cb->value()* ow->scale,ow->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,10 +252,11 @@ void ConfigTaskWidget::updateObjectsFromWidgets()
|
|||||||
void ConfigTaskWidget::setupButtons(QPushButton *update, QPushButton *save)
|
void ConfigTaskWidget::setupButtons(QPushButton *update, QPushButton *save)
|
||||||
{
|
{
|
||||||
smartsave=new smartSaveButton(update,save);
|
smartsave=new smartSaveButton(update,save);
|
||||||
connect(smartsave, SIGNAL(preProcessOperations()), this, SLOT(updateObjectsFromWidgets()));
|
connect(smartsave,SIGNAL(preProcessOperations()), this, SLOT(updateObjectsFromWidgets()));
|
||||||
connect(smartsave,SIGNAL(saveSuccessfull()),this,SLOT(clearDirty()));
|
connect(smartsave,SIGNAL(saveSuccessfull()),this,SLOT(clearDirty()));
|
||||||
connect(smartsave,SIGNAL(beginOp()),this,SLOT(disableObjUpdates()));
|
connect(smartsave,SIGNAL(beginOp()),this,SLOT(disableObjUpdates()));
|
||||||
connect(smartsave,SIGNAL(endOp()),this,SLOT(enableObjUpdates()));
|
connect(smartsave,SIGNAL(endOp()),this,SLOT(enableObjUpdates()));
|
||||||
|
enableControls(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::enableControls(bool enable)
|
void ConfigTaskWidget::enableControls(bool enable)
|
||||||
@ -211,17 +267,23 @@ void ConfigTaskWidget::enableControls(bool enable)
|
|||||||
|
|
||||||
void ConfigTaskWidget::widgetsContentsChanged()
|
void ConfigTaskWidget::widgetsContentsChanged()
|
||||||
{
|
{
|
||||||
dirty=true;
|
setDirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::clearDirty()
|
void ConfigTaskWidget::clearDirty()
|
||||||
{
|
{
|
||||||
dirty=false;
|
setDirty(false);
|
||||||
|
}
|
||||||
|
void ConfigTaskWidget::setDirty(bool value)
|
||||||
|
{
|
||||||
|
dirty=value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigTaskWidget::isDirty()
|
bool ConfigTaskWidget::isDirty()
|
||||||
{
|
{
|
||||||
return dirty;
|
if(isConnected)
|
||||||
|
return dirty;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigTaskWidget::refreshValues()
|
void ConfigTaskWidget::refreshValues()
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
class ConfigTaskWidget: public QWidget
|
class ConfigTaskWidget: public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -51,6 +54,8 @@ public:
|
|||||||
UAVObject * object;
|
UAVObject * object;
|
||||||
UAVObjectField * field;
|
UAVObjectField * field;
|
||||||
QWidget * widget;
|
QWidget * widget;
|
||||||
|
int index;
|
||||||
|
int scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigTaskWidget(QWidget *parent = 0);
|
ConfigTaskWidget(QWidget *parent = 0);
|
||||||
@ -60,9 +65,12 @@ public:
|
|||||||
static double listMean(QList<double> list);
|
static double listMean(QList<double> list);
|
||||||
void addUAVObject(QString objectName);
|
void addUAVObject(QString objectName);
|
||||||
void addWidget(QWidget * widget);
|
void addWidget(QWidget * widget);
|
||||||
void addUAVObjectToWidgetRelation(QString object,QString field,QWidget * widget);
|
void addUAVObjectToWidgetRelation(QString object,QString field,QWidget * widget,int index=0,int scale=1);
|
||||||
|
|
||||||
void setupButtons(QPushButton * update,QPushButton * save);
|
void setupButtons(QPushButton * update,QPushButton * save);
|
||||||
bool isDirty();
|
bool isDirty();
|
||||||
|
void setDirty(bool value);
|
||||||
|
void addUAVObjectToWidgetRelation(QString object, QString field, QWidget *widget, QString index);
|
||||||
public slots:
|
public slots:
|
||||||
void onAutopilotDisconnect();
|
void onAutopilotDisconnect();
|
||||||
void onAutopilotConnect();
|
void onAutopilotConnect();
|
||||||
@ -71,6 +79,8 @@ private slots:
|
|||||||
virtual void refreshValues();
|
virtual void refreshValues();
|
||||||
virtual void updateObjectsFromWidgets();
|
virtual void updateObjectsFromWidgets();
|
||||||
private:
|
private:
|
||||||
|
bool isConnected;
|
||||||
|
QStringList objectsList;
|
||||||
QList <objectToWidget*> objOfInterest;
|
QList <objectToWidget*> objOfInterest;
|
||||||
ExtensionSystem::PluginManager *pm;
|
ExtensionSystem::PluginManager *pm;
|
||||||
UAVObjectManager *objManager;
|
UAVObjectManager *objManager;
|
||||||
|
@ -284,6 +284,10 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FancyTabBar::setCurrentIndex(int index) {
|
void FancyTabBar::setCurrentIndex(int index) {
|
||||||
|
bool proceed=true;
|
||||||
|
emit aboutToChange(&proceed);
|
||||||
|
if(!proceed)
|
||||||
|
return;
|
||||||
m_currentIndex = index;
|
m_currentIndex = index;
|
||||||
update();
|
update();
|
||||||
emit currentChanged(index);
|
emit currentChanged(index);
|
||||||
@ -319,7 +323,6 @@ FancyTabWidget::FancyTabWidget(QWidget *parent, bool isVertical)
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
m_tabBar = new FancyTabBar(this, isVertical);
|
m_tabBar = new FancyTabBar(this, isVertical);
|
||||||
|
|
||||||
m_selectionWidget = new QWidget(this);
|
m_selectionWidget = new QWidget(this);
|
||||||
QBoxLayout *selectionLayout;
|
QBoxLayout *selectionLayout;
|
||||||
if (isVertical) {
|
if (isVertical) {
|
||||||
@ -477,3 +480,7 @@ void FancyTabWidget::setTabToolTip(int index, const QString &toolTip)
|
|||||||
{
|
{
|
||||||
m_tabBar->setTabToolTip(index, toolTip);
|
m_tabBar->setTabToolTip(index, toolTip);
|
||||||
}
|
}
|
||||||
|
QWidget * FancyTabWidget::currentWidget()
|
||||||
|
{
|
||||||
|
return m_modesStack->currentWidget();
|
||||||
|
}
|
||||||
|
@ -91,6 +91,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentChanged(int);
|
void currentChanged(int);
|
||||||
|
void aboutToChange(bool *);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateHover();
|
void updateHover();
|
||||||
@ -116,7 +117,7 @@ class FancyTabWidget : public QWidget
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FancyTabWidget(QWidget *parent = 0, bool isVertical = false);
|
FancyTabWidget(QWidget *parent = 0, bool isVertical = false);
|
||||||
|
FancyTabBar *m_tabBar;
|
||||||
void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label);
|
void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label);
|
||||||
void removeTab(int index);
|
void removeTab(int index);
|
||||||
void setBackgroundBrush(const QBrush &brush);
|
void setBackgroundBrush(const QBrush &brush);
|
||||||
@ -132,6 +133,7 @@ public:
|
|||||||
int currentIndex() const;
|
int currentIndex() const;
|
||||||
QStatusBar *statusBar() const;
|
QStatusBar *statusBar() const;
|
||||||
|
|
||||||
|
QWidget * currentWidget();
|
||||||
signals:
|
signals:
|
||||||
void currentAboutToShow(int index);
|
void currentAboutToShow(int index);
|
||||||
void currentChanged(int index);
|
void currentChanged(int index);
|
||||||
@ -143,7 +145,6 @@ private slots:
|
|||||||
void showWidget(int index);
|
void showWidget(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FancyTabBar *m_tabBar;
|
|
||||||
QWidget *m_cornerWidgetContainer;
|
QWidget *m_cornerWidgetContainer;
|
||||||
QStackedLayout *m_modesStack;
|
QStackedLayout *m_modesStack;
|
||||||
QWidget *m_selectionWidget;
|
QWidget *m_selectionWidget;
|
||||||
|
571
ground/openpilotgcs/src/plugins/config/images/TX.svg
Normal file
571
ground/openpilotgcs/src/plugins/config/images/TX.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 31 KiB |
@ -25,770 +25,105 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QStackedWidget" name="stackedWidget">
|
||||||
<property name="font">
|
<property name="currentIndex">
|
||||||
<font>
|
<number>1</number>
|
||||||
<weight>75</weight>
|
</property>
|
||||||
<bold>true</bold>
|
<widget class="QWidget" name="advancedPage">
|
||||||
</font>
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
</property>
|
<item>
|
||||||
<property name="text">
|
<layout class="QVBoxLayout" name="channelSettings"/>
|
||||||
<string>Receiver Type:</string>
|
</item>
|
||||||
</property>
|
<item>
|
||||||
<property name="alignment">
|
<widget class="QPushButton" name="configurationWizard">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<property name="text">
|
||||||
</property>
|
<string>Start Configuration Wizard</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item row="0" column="5">
|
</item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<item>
|
||||||
<item>
|
<widget class="QCheckBox" name="runCalibration">
|
||||||
<widget class="QLabel" name="RCInputConnected">
|
<property name="text">
|
||||||
<property name="minimumSize">
|
<string>Run Calibration</string>
|
||||||
<size>
|
</property>
|
||||||
<width>234</width>
|
</widget>
|
||||||
<height>54</height>
|
</item>
|
||||||
</size>
|
<item>
|
||||||
</property>
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="font">
|
<property name="orientation">
|
||||||
<font>
|
<enum>Qt::Vertical</enum>
|
||||||
<weight>75</weight>
|
</property>
|
||||||
<bold>true</bold>
|
<property name="sizeHint" stdset="0">
|
||||||
</font>
|
<size>
|
||||||
</property>
|
<width>20</width>
|
||||||
<property name="toolTip">
|
<height>40</height>
|
||||||
<string>Indicates whether OpenPilot is getting a signal from the RC receiver.</string>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
</spacer>
|
||||||
<string>RC Receiver not connected or invalid input configuration (missing channels)</string>
|
</item>
|
||||||
</property>
|
</layout>
|
||||||
<property name="wordWrap">
|
</widget>
|
||||||
<bool>true</bool>
|
<widget class="QWidget" name="wizard">
|
||||||
</property>
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<widget class="QLabel" name="wzText">
|
||||||
</layout>
|
<property name="sizePolicy">
|
||||||
</item>
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
<item row="0" column="9">
|
<horstretch>0</horstretch>
|
||||||
<widget class="QLabel" name="label">
|
<verstretch>0</verstretch>
|
||||||
<property name="text">
|
</sizepolicy>
|
||||||
<string>Rev.</string>
|
</property>
|
||||||
</property>
|
<property name="minimumSize">
|
||||||
<property name="alignment">
|
<size>
|
||||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
<width>0</width>
|
||||||
</property>
|
<height>70</height>
|
||||||
</widget>
|
</size>
|
||||||
</item>
|
</property>
|
||||||
<item row="1" column="0">
|
<property name="text">
|
||||||
<widget class="QComboBox" name="ch0Assign">
|
<string>TextLabel</string>
|
||||||
<property name="iconSize">
|
</property>
|
||||||
<size>
|
<property name="wordWrap">
|
||||||
<width>16</width>
|
<bool>true</bool>
|
||||||
<height>16</height>
|
</property>
|
||||||
</size>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="frame">
|
<item>
|
||||||
<bool>true</bool>
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<widget class="QGraphicsView" name="graphicsView"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="5" colspan="3">
|
<item>
|
||||||
<widget class="QSlider" name="inSlider0">
|
<layout class="QVBoxLayout" name="checkBoxesLayout"/>
|
||||||
<property name="mouseTracking">
|
</item>
|
||||||
<bool>true</bool>
|
</layout>
|
||||||
</property>
|
</item>
|
||||||
<property name="minimum">
|
<item>
|
||||||
<number>1000</number>
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
</property>
|
<item>
|
||||||
<property name="maximum">
|
<widget class="QPushButton" name="wzBack">
|
||||||
<number>2000</number>
|
<property name="text">
|
||||||
</property>
|
<string>Back</string>
|
||||||
<property name="value">
|
</property>
|
||||||
<number>1500</number>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="orientation">
|
<item>
|
||||||
<enum>Qt::Horizontal</enum>
|
<widget class="QPushButton" name="wzNext">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Next</string>
|
||||||
</item>
|
</property>
|
||||||
<item row="1" column="8">
|
</widget>
|
||||||
<widget class="QLabel" name="ch0Max">
|
</item>
|
||||||
<property name="toolTip">
|
<item>
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
<widget class="QPushButton" name="wzCancel">
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
<property name="text">
|
||||||
p, li { white-space: pre-wrap; }
|
<string>Cancel</string>
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
</property>
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
</widget>
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
</item>
|
||||||
</property>
|
</layout>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>2000</string>
|
</layout>
|
||||||
</property>
|
</widget>
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch0Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QComboBox" name="ch1Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider1">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="8">
|
|
||||||
<widget class="QLabel" name="ch1Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch1Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QComboBox" name="ch2Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider2">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="8">
|
|
||||||
<widget class="QLabel" name="ch2Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch2Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QComboBox" name="ch3Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider3">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="8">
|
|
||||||
<widget class="QLabel" name="ch3Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch3Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QComboBox" name="ch4Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider4">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="8">
|
|
||||||
<widget class="QLabel" name="ch4Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch4Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QComboBox" name="ch5Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider5">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="8">
|
|
||||||
<widget class="QLabel" name="ch5Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch5Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QComboBox" name="ch6Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider6">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="8">
|
|
||||||
<widget class="QLabel" name="ch6Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch6Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QComboBox" name="ch7Assign"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="5" colspan="3">
|
|
||||||
<widget class="QSlider" name="inSlider7">
|
|
||||||
<property name="mouseTracking">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1500</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="8">
|
|
||||||
<widget class="QLabel" name="ch7Max">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="9">
|
|
||||||
<widget class="QCheckBox" name="ch7Rev">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check this to reverse the channel.
|
|
||||||
(Useful for transmitters without channel
|
|
||||||
reversal capabilities).</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="0" colspan="10">
|
|
||||||
<widget class="QLabel" name="label_20">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>BEWARE: make sure your engines are not connected when running calibration!
|
|
||||||
</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0" colspan="10">
|
|
||||||
<widget class="QLabel" name="lblMissingInputs">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QCheckBox" name="doRCInputCalibration">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>50</weight>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Start calibrating the RC Inputs.
|
|
||||||
Uncheck/Check to restart calibration.
|
|
||||||
During calibration: move your RC controls over their whole range,
|
|
||||||
then leave them on Neutral, uncheck calibration and save.
|
|
||||||
Neutral should be put at the bottom of the slider for the throttle.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Run Calibration</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="receiverType">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QLabel" name="ch0Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="4">
|
|
||||||
<widget class="QLabel" name="ch1Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</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="ch2Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="4">
|
|
||||||
<widget class="QLabel" name="ch3Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="4">
|
|
||||||
<widget class="QLabel" name="ch4Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="4">
|
|
||||||
<widget class="QLabel" name="ch5Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="4">
|
|
||||||
<widget class="QLabel" name="ch6Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="4">
|
|
||||||
<widget class="QLabel" name="ch7Min">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum channel pulse width</p>
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(microseconds)</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1000</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QLabel" name="ch0Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QLabel" name="ch1Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QLabel" name="ch2Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2">
|
|
||||||
<widget class="QLabel" name="ch3Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="2">
|
|
||||||
<widget class="QLabel" name="ch4Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="2">
|
|
||||||
<widget class="QLabel" name="ch5Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="2">
|
|
||||||
<widget class="QLabel" name="ch6Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="2">
|
|
||||||
<widget class="QLabel" name="ch7Cur">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'FreeSans'; font-size:10pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Current channel value.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1500</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -1243,14 +578,6 @@ Applies and Saves all settings to SD</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>ch0Assign</tabstop>
|
|
||||||
<tabstop>ch1Assign</tabstop>
|
|
||||||
<tabstop>ch2Assign</tabstop>
|
|
||||||
<tabstop>ch3Assign</tabstop>
|
|
||||||
<tabstop>ch4Assign</tabstop>
|
|
||||||
<tabstop>ch5Assign</tabstop>
|
|
||||||
<tabstop>ch6Assign</tabstop>
|
|
||||||
<tabstop>ch7Assign</tabstop>
|
|
||||||
<tabstop>fmsSlider</tabstop>
|
<tabstop>fmsSlider</tabstop>
|
||||||
<tabstop>fmsModePos3</tabstop>
|
<tabstop>fmsModePos3</tabstop>
|
||||||
<tabstop>fmsSsPos3Roll</tabstop>
|
<tabstop>fmsSsPos3Roll</tabstop>
|
||||||
@ -1268,134 +595,5 @@ Applies and Saves all settings to SD</string>
|
|||||||
<resources>
|
<resources>
|
||||||
<include location="../coreplugin/core.qrc"/>
|
<include location="../coreplugin/core.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections/>
|
||||||
<connection>
|
|
||||||
<sender>inSlider0</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch0Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>291</x>
|
|
||||||
<y>93</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>150</x>
|
|
||||||
<y>104</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider1</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch1Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>283</x>
|
|
||||||
<y>137</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>160</x>
|
|
||||||
<y>138</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider2</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch2Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>341</x>
|
|
||||||
<y>163</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>156</x>
|
|
||||||
<y>167</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider3</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch3Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>283</x>
|
|
||||||
<y>211</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>159</x>
|
|
||||||
<y>210</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider4</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch4Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>287</x>
|
|
||||||
<y>239</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>156</x>
|
|
||||||
<y>242</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider5</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch5Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>309</x>
|
|
||||||
<y>272</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>164</x>
|
|
||||||
<y>276</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider6</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch6Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>282</x>
|
|
||||||
<y>300</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>144</x>
|
|
||||||
<y>311</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>inSlider7</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>ch7Cur</receiver>
|
|
||||||
<slot>setNum(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>278</x>
|
|
||||||
<y>339</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>168</x>
|
|
||||||
<y>340</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
</ui>
|
||||||
|
125
ground/openpilotgcs/src/plugins/config/inputchannelform.cpp
Normal file
125
ground/openpilotgcs/src/plugins/config/inputchannelform.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include "inputchannelform.h"
|
||||||
|
#include "ui_inputchannelform.h"
|
||||||
|
|
||||||
|
#include "manualcontrolsettings.h"
|
||||||
|
|
||||||
|
inputChannelForm::inputChannelForm(QWidget *parent,bool showlegend) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::inputChannelForm)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
if(!showlegend)
|
||||||
|
{
|
||||||
|
layout()->removeWidget(ui->legend0);
|
||||||
|
layout()->removeWidget(ui->legend1);
|
||||||
|
layout()->removeWidget(ui->legend2);
|
||||||
|
layout()->removeWidget(ui->legend3);
|
||||||
|
layout()->removeWidget(ui->legend4);
|
||||||
|
layout()->removeWidget(ui->legend5);
|
||||||
|
delete ui->legend0;
|
||||||
|
delete ui->legend1;
|
||||||
|
delete ui->legend2;
|
||||||
|
delete ui->legend3;
|
||||||
|
delete ui->legend4;
|
||||||
|
delete ui->legend5;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(ui->channelMin,SIGNAL(valueChanged(int)),this,SLOT(minMaxUpdated()));
|
||||||
|
connect(ui->channelMax,SIGNAL(valueChanged(int)),this,SLOT(minMaxUpdated()));
|
||||||
|
connect(ui->channelGroup,SIGNAL(currentIndexChanged(int)),this,SLOT(groupUpdated()));
|
||||||
|
connect(ui->channelNeutral,SIGNAL(valueChanged(int)), this, SLOT(neutralUpdated(int)));
|
||||||
|
|
||||||
|
// This is awkward but since we want the UI to be a dropdown but the field is not an enum
|
||||||
|
// it breaks the UAUVObject widget relation of the task gadget. Running the data through
|
||||||
|
// a spin box fixes this
|
||||||
|
connect(ui->channelNumberDropdown,SIGNAL(currentIndexChanged(int)),this,SLOT(channelDropdownUpdated(int)));
|
||||||
|
connect(ui->channelNumber,SIGNAL(valueChanged(int)),this,SLOT(channelNumberUpdated(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inputChannelForm::~inputChannelForm()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the direction of the slider and boundaries
|
||||||
|
*/
|
||||||
|
void inputChannelForm::minMaxUpdated()
|
||||||
|
{
|
||||||
|
bool reverse = ui->channelMin->value() > ui->channelMax->value();
|
||||||
|
if(reverse) {
|
||||||
|
ui->channelNeutral->setMinimum(ui->channelMax->value());
|
||||||
|
ui->channelNeutral->setMaximum(ui->channelMin->value());
|
||||||
|
} else {
|
||||||
|
ui->channelNeutral->setMinimum(ui->channelMin->value());
|
||||||
|
ui->channelNeutral->setMaximum(ui->channelMax->value());
|
||||||
|
}
|
||||||
|
ui->channelRev->setChecked(reverse);
|
||||||
|
ui->channelNeutral->setInvertedAppearance(reverse);
|
||||||
|
ui->channelNeutral->setInvertedControls(reverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inputChannelForm::neutralUpdated(int newval)
|
||||||
|
{
|
||||||
|
ui->neutral->setText(QString::number(newval));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the channel options based on the selected receiver type
|
||||||
|
*
|
||||||
|
* I fully admit this is terrible practice to embed data within UI
|
||||||
|
* like this. Open to suggestions. JC 2011-09-07
|
||||||
|
*/
|
||||||
|
void inputChannelForm::groupUpdated()
|
||||||
|
{
|
||||||
|
ui->channelNumberDropdown->clear();
|
||||||
|
ui->channelNumberDropdown->addItem("Disabled");
|
||||||
|
|
||||||
|
quint8 count = 0;
|
||||||
|
|
||||||
|
switch(ui->channelGroup->currentIndex()) {
|
||||||
|
case -1: // Nothing selected
|
||||||
|
count = 0;
|
||||||
|
break;
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_PWM:
|
||||||
|
count = 8; // Need to make this 6 for CC
|
||||||
|
break;
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_PPM:
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_SPEKTRUM1:
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_SPEKTRUM2:
|
||||||
|
count = 12;
|
||||||
|
break;
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_SBUS:
|
||||||
|
count = 18;
|
||||||
|
break;
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_GCS:
|
||||||
|
count = 5;
|
||||||
|
case ManualControlSettings::CHANNELGROUPS_NONE:
|
||||||
|
count = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
ui->channelNumberDropdown->addItem(QString(tr("Chan %1").arg(i+1)));
|
||||||
|
|
||||||
|
ui->channelNumber->setMaximum(count);
|
||||||
|
ui->channelNumber->setMinimum(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the dropdown from the hidden control
|
||||||
|
*/
|
||||||
|
void inputChannelForm::channelDropdownUpdated(int newval)
|
||||||
|
{
|
||||||
|
ui->channelNumber->setValue(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the hidden control from the dropdown
|
||||||
|
*/
|
||||||
|
void inputChannelForm::channelNumberUpdated(int newval)
|
||||||
|
{
|
||||||
|
ui->channelNumberDropdown->setCurrentIndex(newval);
|
||||||
|
}
|
30
ground/openpilotgcs/src/plugins/config/inputchannelform.h
Normal file
30
ground/openpilotgcs/src/plugins/config/inputchannelform.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef INPUTCHANNELFORM_H
|
||||||
|
#define INPUTCHANNELFORM_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "configinputwidget.h"
|
||||||
|
namespace Ui {
|
||||||
|
class inputChannelForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
class inputChannelForm : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit inputChannelForm(QWidget *parent = 0,bool showlegend=false);
|
||||||
|
~inputChannelForm();
|
||||||
|
friend class ConfigInputWidget;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void minMaxUpdated();
|
||||||
|
void neutralUpdated(int);
|
||||||
|
void groupUpdated();
|
||||||
|
void channelDropdownUpdated(int);
|
||||||
|
void channelNumberUpdated(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::inputChannelForm *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INPUTCHANNELFORM_H
|
260
ground/openpilotgcs/src/plugins/config/inputchannelform.ui
Normal file
260
ground/openpilotgcs/src/plugins/config/inputchannelform.ui
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>inputChannelForm</class>
|
||||||
|
<widget class="QWidget" name="inputChannelForm">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>543</width>
|
||||||
|
<height>49</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalSpacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="channelName">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QComboBox" name="channelGroup">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>6</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<widget class="QSpinBox" name="channelMin">
|
||||||
|
<property name="buttonSymbols">
|
||||||
|
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="8">
|
||||||
|
<widget class="QSpinBox" name="channelMax">
|
||||||
|
<property name="buttonSymbols">
|
||||||
|
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="legend0">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Function</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLabel" name="legend2">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Number</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="legend1">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="8">
|
||||||
|
<widget class="QLabel" name="legend5">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Max</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLabel" name="legend3">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Min</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QLabel" name="legend4">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Neutral</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="6">
|
||||||
|
<widget class="QSlider" name="channelNeutral">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QComboBox" name="channelNumberDropdown">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>4</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maxVisibleItems">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QSpinBox" name="channelNumber">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="10">
|
||||||
|
<widget class="QCheckBox" name="channelRev">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Rev</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="9">
|
||||||
|
<widget class="QLabel" name="neutral">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="5">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>10</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="7">
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>10</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -949,6 +949,27 @@ p, li { white-space: pre-wrap; }
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Neutral (slowest for motor)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -24,8 +24,11 @@ void smartSaveButton::processClick()
|
|||||||
bool error=false;
|
bool error=false;
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectUtilManager* utilMngr = pm->getObject<UAVObjectUtilManager>();
|
UAVObjectUtilManager* utilMngr = pm->getObject<UAVObjectUtilManager>();
|
||||||
foreach(UAVObject * obj,objects)
|
foreach(UAVDataObject * obj,objects)
|
||||||
{
|
{
|
||||||
|
UAVObject::Metadata mdata= obj->getMetadata();
|
||||||
|
if(mdata.gcsAccess==UAVObject::ACCESS_READONLY)
|
||||||
|
continue;
|
||||||
up_result=false;
|
up_result=false;
|
||||||
current_object=obj;
|
current_object=obj;
|
||||||
for(int i=0;i<3;++i)
|
for(int i=0;i<3;++i)
|
||||||
@ -35,7 +38,9 @@ void smartSaveButton::processClick()
|
|||||||
connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
||||||
obj->updated();
|
obj->updated();
|
||||||
timer.start(1000);
|
timer.start(1000);
|
||||||
|
//qDebug()<<"begin loop";
|
||||||
loop.exec();
|
loop.exec();
|
||||||
|
//qDebug()<<"end loop";
|
||||||
timer.stop();
|
timer.stop();
|
||||||
disconnect(obj,SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(transaction_finished(UAVObject*, bool)));
|
disconnect(obj,SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(transaction_finished(UAVObject*, bool)));
|
||||||
disconnect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
disconnect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
||||||
@ -44,30 +49,32 @@ void smartSaveButton::processClick()
|
|||||||
}
|
}
|
||||||
if(up_result==false)
|
if(up_result==false)
|
||||||
{
|
{
|
||||||
|
//qDebug()<<"Object upload error:"<<obj->getName();
|
||||||
error=true;
|
error=true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sv_result=false;
|
sv_result=false;
|
||||||
current_objectID=obj->getObjID();
|
current_objectID=obj->getObjID();
|
||||||
if(save)
|
if(save && (obj->isSettings()))
|
||||||
{
|
{
|
||||||
for(int i=0;i<3;++i)
|
for(int i=0;i<3;++i)
|
||||||
{
|
{
|
||||||
connect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool)));
|
//qDebug()<<"try to save:"<<obj->getName();
|
||||||
connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
connect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool)));
|
||||||
utilMngr->saveObjectToSD(obj);
|
connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
||||||
timer.start(1000);
|
utilMngr->saveObjectToSD(obj);
|
||||||
loop.exec();
|
timer.start(1000);
|
||||||
timer.stop();
|
loop.exec();
|
||||||
disconnect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool)));
|
timer.stop();
|
||||||
disconnect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
disconnect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool)));
|
||||||
if(sv_result)
|
disconnect(&timer,SIGNAL(timeout()),&loop,SLOT(quit()));
|
||||||
break;
|
if(sv_result)
|
||||||
}
|
break;
|
||||||
if(sv_result==false)
|
}
|
||||||
{
|
if(sv_result==false)
|
||||||
error=true;
|
{
|
||||||
}
|
error=true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button->setEnabled(true);
|
button->setEnabled(true);
|
||||||
@ -83,14 +90,15 @@ void smartSaveButton::processClick()
|
|||||||
emit endOp();
|
emit endOp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void smartSaveButton::setObjects(QList<UAVObject *> list)
|
void smartSaveButton::setObjects(QList<UAVDataObject *> list)
|
||||||
{
|
{
|
||||||
objects=list;
|
objects=list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void smartSaveButton::addObject(UAVObject * obj)
|
void smartSaveButton::addObject(UAVDataObject * obj)
|
||||||
{
|
{
|
||||||
objects.append(obj);
|
if(!objects.contains(obj))
|
||||||
|
objects.append(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void smartSaveButton::clearObjects()
|
void smartSaveButton::clearObjects()
|
||||||
@ -111,6 +119,7 @@ void smartSaveButton::saving_finished(int id, bool result)
|
|||||||
if(id==current_objectID)
|
if(id==current_objectID)
|
||||||
{
|
{
|
||||||
sv_result=result;
|
sv_result=result;
|
||||||
|
//qDebug()<<"saving_finished result="<<result;
|
||||||
loop.quit();
|
loop.quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ public:
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
smartSaveButton(QPushButton * update,QPushButton * save);
|
smartSaveButton(QPushButton * update,QPushButton * save);
|
||||||
void setObjects(QList<UAVObject *>);
|
void setObjects(QList<UAVDataObject *>);
|
||||||
void addObject(UAVObject *);
|
void addObject(UAVDataObject *);
|
||||||
void clearObjects();
|
void clearObjects();
|
||||||
signals:
|
signals:
|
||||||
void preProcessOperations();
|
void preProcessOperations();
|
||||||
@ -34,11 +34,11 @@ private:
|
|||||||
QPushButton *bupdate;
|
QPushButton *bupdate;
|
||||||
QPushButton *bsave;
|
QPushButton *bsave;
|
||||||
quint32 current_objectID;
|
quint32 current_objectID;
|
||||||
UAVObject * current_object;
|
UAVDataObject * current_object;
|
||||||
bool up_result;
|
bool up_result;
|
||||||
bool sv_result;
|
bool sv_result;
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QList<UAVObject *> objects;
|
QList<UAVDataObject *> objects;
|
||||||
protected:
|
protected:
|
||||||
public slots:
|
public slots:
|
||||||
void enableControls(bool value);
|
void enableControls(bool value);
|
||||||
|
@ -601,21 +601,21 @@ When you change one, the other is updated.</string>
|
|||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="manualRoll">
|
<widget class="QSpinBox" name="manualRoll">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="2" column="2">
|
||||||
<widget class="QSpinBox" name="manualPitch">
|
<widget class="QSpinBox" name="manualPitch">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="3">
|
<item row="2" column="3">
|
||||||
<widget class="QSpinBox" name="manualYaw">
|
<widget class="QSpinBox" name="manualYaw">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -644,21 +644,21 @@ When you change one, the other is updated.</string>
|
|||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="maximumRoll">
|
<widget class="QSpinBox" name="maximumRoll">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QSpinBox" name="maximumPitch">
|
<widget class="QSpinBox" name="maximumPitch">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="3">
|
<item row="3" column="3">
|
||||||
<widget class="QSpinBox" name="maximumYaw">
|
<widget class="QSpinBox" name="maximumYaw">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>300</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -385,8 +385,15 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
|||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject((plotData->uavObject)));
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject((plotData->uavObject)));
|
||||||
|
if(!obj) {
|
||||||
|
qDebug() << "Object " << plotData->uavObject << " is missing";
|
||||||
|
return;
|
||||||
|
}
|
||||||
UAVObjectField* field = obj->getField(plotData->uavField);
|
UAVObjectField* field = obj->getField(plotData->uavField);
|
||||||
|
if(!field) {
|
||||||
|
qDebug() << "Field " << plotData->uavField << " of object " << plotData->uavObject << " is missing";
|
||||||
|
return;
|
||||||
|
}
|
||||||
QString units = field->getUnits();
|
QString units = field->getUnits();
|
||||||
|
|
||||||
if(units == 0)
|
if(units == 0)
|
||||||
|
@ -70,6 +70,8 @@ HEADERS += $$UAVOBJECT_SYNTHETICS/accessorydesired.h \
|
|||||||
$$UAVOBJECT_SYNTHETICS/sonaraltitude.h \
|
$$UAVOBJECT_SYNTHETICS/sonaraltitude.h \
|
||||||
$$UAVOBJECT_SYNTHETICS/flightstatus.h \
|
$$UAVOBJECT_SYNTHETICS/flightstatus.h \
|
||||||
$$UAVOBJECT_SYNTHETICS/hwsettings.h \
|
$$UAVOBJECT_SYNTHETICS/hwsettings.h \
|
||||||
|
$$UAVOBJECT_SYNTHETICS/gcsreceiver.h \
|
||||||
|
$$UAVOBJECT_SYNTHETICS/receiveractivity.h \
|
||||||
$$UAVOBJECT_SYNTHETICS/attitudesettings.h \
|
$$UAVOBJECT_SYNTHETICS/attitudesettings.h \
|
||||||
$$UAVOBJECT_SYNTHETICS/cameradesired.h
|
$$UAVOBJECT_SYNTHETICS/cameradesired.h
|
||||||
|
|
||||||
@ -121,5 +123,7 @@ SOURCES += $$UAVOBJECT_SYNTHETICS/accessorydesired.cpp \
|
|||||||
$$UAVOBJECT_SYNTHETICS/uavobjectsinit.cpp \
|
$$UAVOBJECT_SYNTHETICS/uavobjectsinit.cpp \
|
||||||
$$UAVOBJECT_SYNTHETICS/flightstatus.cpp \
|
$$UAVOBJECT_SYNTHETICS/flightstatus.cpp \
|
||||||
$$UAVOBJECT_SYNTHETICS/hwsettings.cpp \
|
$$UAVOBJECT_SYNTHETICS/hwsettings.cpp \
|
||||||
|
$$UAVOBJECT_SYNTHETICS/gcsreceiver.cpp \
|
||||||
|
$$UAVOBJECT_SYNTHETICS/receiveractivity.cpp \
|
||||||
$$UAVOBJECT_SYNTHETICS/attitudesettings.cpp \
|
$$UAVOBJECT_SYNTHETICS/attitudesettings.cpp \
|
||||||
$$UAVOBJECT_SYNTHETICS/cameradesired.cpp
|
$$UAVOBJECT_SYNTHETICS/cameradesired.cpp
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QErrorMessage>
|
||||||
|
#include <objectpersistence.h>
|
||||||
|
|
||||||
// ******************************
|
// ******************************
|
||||||
// constructor/destructor
|
// constructor/destructor
|
||||||
@ -168,18 +170,30 @@ void UAVObjectUtilManager::objectPersistenceTransactionCompleted(UAVObject* obj,
|
|||||||
*/
|
*/
|
||||||
void UAVObjectUtilManager::objectPersistenceOperationFailed()
|
void UAVObjectUtilManager::objectPersistenceOperationFailed()
|
||||||
{
|
{
|
||||||
qDebug() << "objectPersistenceOperationFailed";
|
|
||||||
if(saveState == AWAITING_COMPLETED) {
|
if(saveState == AWAITING_COMPLETED) {
|
||||||
//TODO: some warning that this operation failed somehow
|
//TODO: some warning that this operation failed somehow
|
||||||
// We have to disconnect the object persistence 'updated' signal
|
// We have to disconnect the object persistence 'updated' signal
|
||||||
// and ask to save the next object:
|
// and ask to save the next object:
|
||||||
UAVObject *obj = getObjectManager()->getObject(ObjectPersistence::NAME);
|
|
||||||
obj->disconnect(this);
|
ObjectPersistence * objectPersistence = ObjectPersistence::GetInstance(getObjectManager());
|
||||||
queue.dequeue(); // We can now remove the object, it failed anyway.
|
Q_ASSERT(objectPersistence);
|
||||||
|
|
||||||
|
UAVObject* obj = queue.dequeue(); // We can now remove the object, it failed anyway.
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
objectPersistence->disconnect(this);
|
||||||
|
|
||||||
saveState = IDLE;
|
saveState = IDLE;
|
||||||
emit saveCompleted(obj->getField("ObjectID")->getValue().toInt(), false);
|
emit saveCompleted(obj->getObjID(), false);
|
||||||
|
|
||||||
|
// For now cause error message here to make sure user knows
|
||||||
|
QErrorMessage err;
|
||||||
|
err.showMessage("Saving object " + obj->getName() + " failed. Please try again");
|
||||||
|
err.exec();
|
||||||
|
|
||||||
saveNextObject();
|
saveNextObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user