1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-20 10:54:14 +01:00

Merge branch 'next' into CC_GPS

This commit is contained in:
Corvus Corax 2011-11-11 11:44:11 +01:00
commit aa69027cb2
49 changed files with 1608 additions and 1210 deletions

View File

@ -1,5 +1,21 @@
Short summary of changes. For a complete list see the git log.
2011-11-04
New Spektrum/JR satellite receiver driver implementation.
It now provides explicit selection of DSM2 (and DSMJ), DSMX (10bit) and
DSMX (11bit) serial protocol variations to better serve different frame
and resolution modes. The protocol name used now is DSM instead of
previously used Spektrum to make it less ambiguous when used with JR
2.4GHz radios.
2011-10-20
Inputs can be remapped to outputs to allow up to 10 channels of control. The
receiver inputs remap as follows:
Receiver 3 because output channel 7
Receiver 4 because output channel 8
Receiver 5 because output channel 9
Receiver 6 because output channel 10
2011-10-11
Fix for the Mac telemetry rates and specifically how long enumeration took.

View File

@ -193,7 +193,7 @@ SRC += $(PIOSSTM32F10X)/pios_i2c.c
SRC += $(PIOSSTM32F10X)/pios_spi.c
SRC += $(PIOSSTM32F10X)/pios_ppm.c
SRC += $(PIOSSTM32F10X)/pios_pwm.c
SRC += $(PIOSSTM32F10X)/pios_spektrum.c
SRC += $(PIOSSTM32F10X)/pios_dsm.c
SRC += $(PIOSSTM32F10X)/pios_sbus.c
SRC += $(PIOSSTM32F10X)/pios_debug.c
SRC += $(PIOSSTM32F10X)/pios_gpio.c

View File

@ -46,7 +46,7 @@
#define PIOS_INCLUDE_RCVR
/* Supported receiver interfaces */
#define PIOS_INCLUDE_SPEKTRUM
#define PIOS_INCLUDE_DSM
#define PIOS_INCLUDE_SBUS
#define PIOS_INCLUDE_PPM
#define PIOS_INCLUDE_PWM

View File

@ -410,6 +410,133 @@ static const struct pios_tim_channel pios_tim_servoport_all_pins[] = {
},
};
static const struct pios_tim_channel pios_tim_servoport_rcvrport_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,
},
},
},
// Receiver port pins
// S3-S6 inputs are used as outputs in this case
{
.timer = TIM3,
.timer_chan = TIM_Channel_3,
.pin = {
.gpio = GPIOB,
.init = {
.GPIO_Pin = GPIO_Pin_0,
.GPIO_Mode = GPIO_Mode_AF_PP,
.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_AF_PP,
.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_AF_PP,
.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_AF_PP,
.GPIO_Speed = GPIO_Speed_2MHz,
},
},
},
};
#if defined(PIOS_INCLUDE_USART)
#include "pios_usart_priv.h"
@ -568,13 +695,13 @@ static const struct pios_usart_cfg pios_usart_gps_flexi_cfg = {
};
#endif /* PIOS_INCLUDE_GPS */
#if defined(PIOS_INCLUDE_SPEKTRUM)
#if defined(PIOS_INCLUDE_DSM)
/*
* SPEKTRUM USART
* Spektrum/JR DSM USART
*/
#include <pios_spektrum_priv.h>
#include <pios_dsm_priv.h>
static const struct pios_usart_cfg pios_usart_spektrum_main_cfg = {
static const struct pios_usart_cfg pios_usart_dsm_main_cfg = {
.regs = USART1,
.init = {
.USART_BaudRate = 115200,
@ -610,7 +737,7 @@ static const struct pios_usart_cfg pios_usart_spektrum_main_cfg = {
},
};
static const struct pios_spektrum_cfg pios_spektrum_main_cfg = {
static const struct pios_dsm_cfg pios_dsm_main_cfg = {
.bind = {
.gpio = GPIOA,
.init = {
@ -619,10 +746,9 @@ static const struct pios_spektrum_cfg pios_spektrum_main_cfg = {
.GPIO_Mode = GPIO_Mode_Out_PP,
},
},
.remap = 0,
};
static const struct pios_usart_cfg pios_usart_spektrum_flexi_cfg = {
static const struct pios_usart_cfg pios_usart_dsm_flexi_cfg = {
.regs = USART3,
.init = {
.USART_BaudRate = 115200,
@ -658,7 +784,7 @@ static const struct pios_usart_cfg pios_usart_spektrum_flexi_cfg = {
},
};
static const struct pios_spektrum_cfg pios_spektrum_flexi_cfg = {
static const struct pios_dsm_cfg pios_dsm_flexi_cfg = {
.bind = {
.gpio = GPIOB,
.init = {
@ -667,14 +793,13 @@ static const struct pios_spektrum_cfg pios_spektrum_flexi_cfg = {
.GPIO_Mode = GPIO_Mode_Out_PP,
},
},
.remap = 0,
};
#endif /* PIOS_INCLUDE_SPEKTRUM */
#endif /* PIOS_INCLUDE_DSM */
#if defined(PIOS_INCLUDE_SBUS)
/*
* SBUS USART
* S.Bus USART
*/
#include <pios_sbus_priv.h>
@ -795,6 +920,22 @@ const struct pios_servo_cfg pios_servo_cfg = {
.num_channels = NELEMENTS(pios_tim_servoport_all_pins),
};
const struct pios_servo_cfg pios_servo_rcvr_cfg = {
.tim_oc_init = {
.TIM_OCMode = TIM_OCMode_PWM1,
.TIM_OutputState = TIM_OutputState_Enable,
.TIM_OutputNState = TIM_OutputNState_Disable,
.TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION,
.TIM_OCPolarity = TIM_OCPolarity_High,
.TIM_OCNPolarity = TIM_OCPolarity_High,
.TIM_OCIdleState = TIM_OCIdleState_Reset,
.TIM_OCNIdleState = TIM_OCNIdleState_Reset,
},
.channels = pios_tim_servoport_rcvrport_pins,
.num_channels = NELEMENTS(pios_tim_servoport_rcvrport_pins),
};
/*
* PPM Inputs
*/
@ -916,7 +1057,7 @@ void PIOS_I2C_main_adapter_er_irq_handler(void)
#include "pios_rcvr_priv.h"
/* One slot per selectable receiver group.
* eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS
* eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS
* NOTE: No slot in this map for NONE.
*/
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];
@ -1025,7 +1166,7 @@ void PIOS_Board_Init(void) {
}
uint32_t pios_sbus_id;
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);
}
@ -1056,31 +1197,48 @@ void PIOS_Board_Init(void) {
}
#endif /* PIOS_INCLUDE_GPS */
break;
case HWSETTINGS_CC_MAINPORT_SPEKTRUM1:
case HWSETTINGS_CC_MAINPORT_SPEKTRUM2:
#if defined(PIOS_INCLUDE_SPEKTRUM)
case HWSETTINGS_CC_MAINPORT_DSM2:
case HWSETTINGS_CC_MAINPORT_DSMX10BIT:
case HWSETTINGS_CC_MAINPORT_DSMX11BIT:
#if defined(PIOS_INCLUDE_DSM)
{
uint32_t pios_usart_spektrum_id;
if (PIOS_USART_Init(&pios_usart_spektrum_id, &pios_usart_spektrum_main_cfg)) {
enum pios_dsm_proto proto;
switch (hwsettings_cc_mainport) {
case HWSETTINGS_CC_MAINPORT_DSM2:
proto = PIOS_DSM_PROTO_DSM2;
break;
case HWSETTINGS_CC_MAINPORT_DSMX10BIT:
proto = PIOS_DSM_PROTO_DSMX10BIT;
break;
case HWSETTINGS_CC_MAINPORT_DSMX11BIT:
proto = PIOS_DSM_PROTO_DSMX11BIT;
break;
default:
PIOS_Assert(0);
break;
}
uint32_t pios_usart_dsm_id;
if (PIOS_USART_Init(&pios_usart_dsm_id, &pios_usart_dsm_main_cfg)) {
PIOS_Assert(0);
}
uint32_t pios_spektrum_id;
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_main_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, 0)) {
uint32_t pios_dsm_id;
if (PIOS_DSM_Init(&pios_dsm_id,
&pios_dsm_main_cfg,
&pios_usart_com_driver,
pios_usart_dsm_id,
proto, 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)) {
uint32_t pios_dsm_rcvr_id;
if (PIOS_RCVR_Init(&pios_dsm_rcvr_id, &pios_dsm_rcvr_driver, pios_dsm_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;
}
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_DSMMAINPORT] = pios_dsm_rcvr_id;
}
#endif /* PIOS_INCLUDE_SPEKTRUM */
#endif /* PIOS_INCLUDE_DSM */
break;
case HWSETTINGS_CC_MAINPORT_COMAUX:
break;
@ -1129,31 +1287,48 @@ void PIOS_Board_Init(void) {
}
#endif /* PIOS_INCLUDE_GPS */
break;
case HWSETTINGS_CC_FLEXIPORT_SPEKTRUM1:
case HWSETTINGS_CC_FLEXIPORT_SPEKTRUM2:
#if defined(PIOS_INCLUDE_SPEKTRUM)
case HWSETTINGS_CC_FLEXIPORT_DSM2:
case HWSETTINGS_CC_FLEXIPORT_DSMX10BIT:
case HWSETTINGS_CC_FLEXIPORT_DSMX11BIT:
#if defined(PIOS_INCLUDE_DSM)
{
uint32_t pios_usart_spektrum_id;
if (PIOS_USART_Init(&pios_usart_spektrum_id, &pios_usart_spektrum_flexi_cfg)) {
enum pios_dsm_proto proto;
switch (hwsettings_cc_flexiport) {
case HWSETTINGS_CC_FLEXIPORT_DSM2:
proto = PIOS_DSM_PROTO_DSM2;
break;
case HWSETTINGS_CC_FLEXIPORT_DSMX10BIT:
proto = PIOS_DSM_PROTO_DSMX10BIT;
break;
case HWSETTINGS_CC_FLEXIPORT_DSMX11BIT:
proto = PIOS_DSM_PROTO_DSMX11BIT;
break;
default:
PIOS_Assert(0);
break;
}
uint32_t pios_usart_dsm_id;
if (PIOS_USART_Init(&pios_usart_dsm_id, &pios_usart_dsm_flexi_cfg)) {
PIOS_Assert(0);
}
uint32_t pios_spektrum_id;
if (PIOS_SPEKTRUM_Init(&pios_spektrum_id, &pios_spektrum_flexi_cfg, &pios_usart_com_driver, pios_usart_spektrum_id, hwsettings_DSMxBind)) {
uint32_t pios_dsm_id;
if (PIOS_DSM_Init(&pios_dsm_id,
&pios_dsm_flexi_cfg,
&pios_usart_com_driver,
pios_usart_dsm_id,
proto, hwsettings_DSMxBind)) {
PIOS_Assert(0);
}
uint32_t pios_spektrum_rcvr_id;
if (PIOS_RCVR_Init(&pios_spektrum_rcvr_id, &pios_spektrum_rcvr_driver, pios_spektrum_id)) {
uint32_t pios_dsm_rcvr_id;
if (PIOS_RCVR_Init(&pios_dsm_rcvr_id, &pios_dsm_rcvr_driver, pios_dsm_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;
}
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_DSMFLEXIPORT] = pios_dsm_rcvr_id;
}
#endif /* PIOS_INCLUDE_SPEKTRUM */
#endif /* PIOS_INCLUDE_DSM */
break;
case HWSETTINGS_CC_FLEXIPORT_COMAUX:
break;
@ -1190,6 +1365,7 @@ void PIOS_Board_Init(void) {
#endif /* PIOS_INCLUDE_PWM */
break;
case HWSETTINGS_CC_RCVRPORT_PPM:
case HWSETTINGS_CC_RCVRPORT_PPMSERVO:
#if defined(PIOS_INCLUDE_PPM)
{
uint32_t pios_ppm_id;
@ -1219,7 +1395,17 @@ void PIOS_Board_Init(void) {
GPIO_PinRemapConfig( GPIO_Remap_SWJ_NoJTRST, ENABLE);
#ifndef PIOS_DEBUG_ENABLE_DEBUG_PINS
PIOS_Servo_Init(&pios_servo_cfg);
switch (hwsettings_rcvrport) {
case HWSETTINGS_CC_RCVRPORT_DISABLED:
case HWSETTINGS_CC_RCVRPORT_PWM:
case HWSETTINGS_CC_RCVRPORT_PPM:
PIOS_Servo_Init(&pios_servo_cfg);
break;
case HWSETTINGS_CC_RCVRPORT_PPMSERVO:
case HWSETTINGS_CC_RCVRPORT_SERVO:
PIOS_Servo_Init(&pios_servo_rcvr_cfg);
break;
}
#else
PIOS_DEBUG_Init(&pios_tim_servo_all_channels, NELEMENTS(pios_tim_servo_all_channels));
#endif /* PIOS_DEBUG_ENABLE_DEBUG_PINS */

View File

@ -439,11 +439,11 @@ static bool updateRcvrActivityCompare(uint32_t rcvr_id, struct rcvr_activity_fsm
case MANUALCONTROLSETTINGS_CHANNELGROUPS_PPM:
group = RECEIVERACTIVITY_ACTIVEGROUP_PPM;
break;
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1:
group = RECEIVERACTIVITY_ACTIVEGROUP_SPEKTRUM1;
case MANUALCONTROLSETTINGS_CHANNELGROUPS_DSMMAINPORT:
group = RECEIVERACTIVITY_ACTIVEGROUP_DSMMAINPORT;
break;
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM2:
group = RECEIVERACTIVITY_ACTIVEGROUP_SPEKTRUM2;
case MANUALCONTROLSETTINGS_CHANNELGROUPS_DSMFLEXIPORT:
group = RECEIVERACTIVITY_ACTIVEGROUP_DSMFLEXIPORT;
break;
case MANUALCONTROLSETTINGS_CHANNELGROUPS_SBUS:
group = RECEIVERACTIVITY_ACTIVEGROUP_SBUS;

View File

@ -390,25 +390,24 @@ static void updateSystemAlarms()
EventStats evStats;
SystemStatsGet(&stats);
// Check heap
if (stats.HeapRemaining < HEAP_LIMIT_CRITICAL) {
AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY, SYSTEMALARMS_ALARM_CRITICAL);
} else if (stats.HeapRemaining < HEAP_LIMIT_WARNING) {
AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY, SYSTEMALARMS_ALARM_WARNING);
} else {
AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY);
}
// Check heap, IRQ stack and malloc failures
if ( mallocFailed
|| (stats.HeapRemaining < HEAP_LIMIT_CRITICAL)
#if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
// Check IRQ stack
if (stats.IRQStackRemaining < IRQSTACK_LIMIT_CRITICAL) {
|| (stats.IRQStackRemaining < IRQSTACK_LIMIT_CRITICAL)
#endif
) {
AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY, SYSTEMALARMS_ALARM_CRITICAL);
} else if (stats.IRQStackRemaining < IRQSTACK_LIMIT_WARNING) {
} else if (
(stats.HeapRemaining < HEAP_LIMIT_WARNING)
#if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
|| (stats.IRQStackRemaining < IRQSTACK_LIMIT_WARNING)
#endif
) {
AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY, SYSTEMALARMS_ALARM_WARNING);
} else {
AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY);
}
#endif
// Check CPU load
if (stats.CPULoad > CPULOAD_LIMIT_CRITICAL) {
@ -426,13 +425,6 @@ static void updateSystemAlarms()
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)
// Check for SD card
if (PIOS_SDCARD_IsMounted() == 0) {

View File

@ -169,7 +169,7 @@ SRC += $(PIOSSTM32F10X)/pios_i2c.c
SRC += $(PIOSSTM32F10X)/pios_spi.c
SRC += $(PIOSSTM32F10X)/pios_ppm.c
SRC += $(PIOSSTM32F10X)/pios_pwm.c
SRC += $(PIOSSTM32F10X)/pios_spektrum.c
SRC += $(PIOSSTM32F10X)/pios_dsm.c
SRC += $(PIOSSTM32F10X)/pios_sbus.c
SRC += $(PIOSSTM32F10X)/pios_tim.c
SRC += $(PIOSSTM32F10X)/pios_debug.c

View File

@ -44,7 +44,7 @@
#define PIOS_INCLUDE_RCVR
#define PIOS_INCLUDE_SPEKTRUM
#define PIOS_INCLUDE_DSM
//#define PIOS_INCLUDE_SBUS
#define PIOS_INCLUDE_PWM
#define PIOS_INCLUDE_PPM

View File

@ -143,11 +143,11 @@ static void TaskTesting(void *pvParameters)
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u\r", PIOS_BMP085_GetPressure());
*/
#if defined(PIOS_INCLUDE_SPEKTRUM)
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u,%u,%u,%u,%u,%u,%u,%u\r", PIOS_SPEKTRUM_Get(0), PIOS_SPEKTRUM_Get(1), PIOS_SPEKTRUM_Get(2), PIOS_SPEKTRUM_Get(3), PIOS_SPEKTRUM_Get(4), PIOS_SPEKTRUM_Get(5), PIOS_SPEKTRUM_Get(6), PIOS_SPEKTRUM_Get(7));
#if defined(PIOS_INCLUDE_DSM)
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u,%u,%u,%u,%u,%u,%u,%u\r", PIOS_DSM_Get(0), PIOS_DSM_Get(1), PIOS_DSM_Get(2), PIOS_DSM_Get(3), PIOS_DSM_Get(4), PIOS_DSM_Get(5), PIOS_DSM_Get(6), PIOS_DSM_Get(7));
#endif
#if defined(PIOS_INCLUDE_SBUS)
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u,%u,%u,%u,%u,%u,%u,%u\r", PIOS_SBUS_Get(0), PIOS_SBUS_Get(1), PIOS_SBUS_Get(2), PIOS_SBUS_Get(3), PIOS_SBUS_Get(4), PIOS_SBUS_Get(5), PIOS_SBUS_Get(6), PIOS_SBUS_Get(7));
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u,%u,%u,%u,%u,%u,%u,%u\r", PIOS_SBus_Get(0), PIOS_SBus_Get(1), PIOS_SBus_Get(2), PIOS_SBus_Get(3), PIOS_SBus_Get(4), PIOS_SBus_Get(5), PIOS_SBus_Get(6), PIOS_SBus_Get(7));
#endif
#if defined(PIOS_INCLUDE_PWM)
PIOS_COM_SendFormattedStringNonBlocking(COM_DEBUG_USART, "%u,%u,%u,%u,%u,%u,%u,%u uS\r", PIOS_PWM_Get(0), PIOS_PWM_Get(1), PIOS_PWM_Get(2), PIOS_PWM_Get(3), PIOS_PWM_Get(4), PIOS_PWM_Get(5), PIOS_PWM_Get(6), PIOS_PWM_Get(7));

View File

@ -538,13 +538,13 @@ void PIOS_RTC_IRQ_Handler (void)
#endif
#if defined(PIOS_INCLUDE_SPEKTRUM)
#if defined(PIOS_INCLUDE_DSM)
/*
* SPEKTRUM USART
* Spektrum/JR DSM USART
*/
#include <pios_spektrum_priv.h>
#include <pios_dsm_priv.h>
static const struct pios_usart_cfg pios_usart_spektrum_cfg = {
static const struct pios_usart_cfg pios_usart_dsm_cfg = {
.regs = USART1,
.init = {
.USART_BaudRate = 115200,
@ -580,7 +580,7 @@ static const struct pios_usart_cfg pios_usart_spektrum_cfg = {
},
};
static const struct pios_spektrum_cfg pios_spektrum_cfg = {
static const struct pios_dsm_cfg pios_dsm_cfg = {
.bind = {
.gpio = GPIOA,
.init = {
@ -589,10 +589,9 @@ static const struct pios_spektrum_cfg pios_spektrum_cfg = {
.GPIO_Mode = GPIO_Mode_Out_PP,
},
},
.remap = 0,
};
#endif /* PIOS_COM_SPEKTRUM */
#endif /* PIOS_COM_DSM */
#if defined(PIOS_INCLUDE_SBUS)
#error PIOS_INCLUDE_SBUS not implemented
@ -1035,7 +1034,7 @@ static const struct stm32_gpio pios_debug_pins[] = {
#include "pios_rcvr_priv.h"
/* One slot per selectable receiver group.
* eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS
* eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS
* NOTE: No slot in this map for NONE.
*/
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];
@ -1063,7 +1062,7 @@ uint32_t pios_com_telem_rf_id;
uint32_t pios_com_telem_usb_id;
uint32_t pios_com_gps_id;
uint32_t pios_com_aux_id;
uint32_t pios_com_spektrum_id;
uint32_t pios_com_dsm_id;
#include "ahrs_spi_comm.h"
@ -1204,24 +1203,46 @@ void PIOS_Board_Init(void) {
case HWSETTINGS_OP_RCVRPORT_DEBUG:
/* Not supported yet */
break;
case HWSETTINGS_OP_RCVRPORT_SPEKTRUM1:
#if defined(PIOS_INCLUDE_SPEKTRUM)
case HWSETTINGS_OP_RCVRPORT_DSM2:
case HWSETTINGS_OP_RCVRPORT_DSMX10BIT:
case HWSETTINGS_OP_RCVRPORT_DSMX11BIT:
#if defined(PIOS_INCLUDE_DSM)
{
uint32_t pios_usart_spektrum_id;
if (PIOS_USART_Init(&pios_usart_spektrum_id, &pios_usart_spektrum_cfg)) {
enum pios_dsm_proto proto;
switch (hwsettings_rcvrport) {
case HWSETTINGS_OP_RCVRPORT_DSM2:
proto = PIOS_DSM_PROTO_DSM2;
break;
case HWSETTINGS_OP_RCVRPORT_DSMX10BIT:
proto = PIOS_DSM_PROTO_DSMX10BIT;
break;
case HWSETTINGS_OP_RCVRPORT_DSMX11BIT:
proto = PIOS_DSM_PROTO_DSMX11BIT;
break;
default:
PIOS_Assert(0);
break;
}
uint32_t pios_usart_dsm_id;
if (PIOS_USART_Init(&pios_usart_dsm_id, &pios_usart_dsm_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)) {
uint32_t pios_dsm_id;
if (PIOS_DSM_Init(&pios_dsm_id,
&pios_dsm_cfg,
&pios_usart_com_driver,
pios_usart_dsm_id,
proto, 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)) {
uint32_t pios_dsm_rcvr_id;
if (PIOS_RCVR_Init(&pios_dsm_rcvr_id, &pios_dsm_rcvr_driver, pios_dsm_id)) {
PIOS_Assert(0);
}
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_SPEKTRUM1] = pios_spektrum_rcvr_id;
pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_DSMMAINPORT] = pios_dsm_rcvr_id;
}
#endif
break;

View File

@ -40,7 +40,7 @@
#include "pios_rcvr_priv.h"
/* One slot per selectable receiver group.
* eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS
* eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS
* NOTE: No slot in this map for NONE.
*/
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];

View File

@ -222,10 +222,16 @@ extern uint32_t pios_com_telem_usb_id;
#define PIOS_PWM_NUM_INPUTS 6
//-------------------------
// Receiver SPEKTRUM input
// Receiver DSM input
//-------------------------
#define PIOS_SPEKTRUM_MAX_DEVS 2
#define PIOS_SPEKTRUM_NUM_INPUTS 12
#define PIOS_DSM_MAX_DEVS 2
#define PIOS_DSM_NUM_INPUTS 12
//-------------------------
// Receiver S.Bus input
//-------------------------
#define PIOS_SBUS_MAX_DEVS 1
#define PIOS_SBUS_NUM_INPUTS (16+2)
//-------------------------
// Servo outputs

View File

@ -195,10 +195,16 @@ extern uint32_t pios_com_aux_id;
#define PIOS_PWM_NUM_INPUTS 8
//-------------------------
// Receiver SPEKTRUM input
// Receiver DSM input
//-------------------------
#define PIOS_SPEKTRUM_MAX_DEVS 1
#define PIOS_SPEKTRUM_NUM_INPUTS 12
#define PIOS_DSM_MAX_DEVS 1
#define PIOS_DSM_NUM_INPUTS 12
//-------------------------
// Receiver S.Bus input
//-------------------------
#define PIOS_SBUS_MAX_DEVS 0
#define PIOS_SBUS_NUM_INPUTS (16+2)
//-------------------------
// Servo outputs

View File

@ -32,8 +32,8 @@
#include "pios.h"
#if defined(PIOS_INCLUDE_HCSR04)
#if !(defined(PIOS_INCLUDE_SPEKTRUM) || defined(PIOS_INCLUDE_SBUS))
#error Only supported with Spektrum or S.Bus interface!
#if !(defined(PIOS_INCLUDE_DSM) || defined(PIOS_INCLUDE_SBUS))
#error Only supported with Spektrum/JR DSM or S.Bus interface!
#endif
/* Local Variables */

View File

@ -0,0 +1,407 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_DSM Spektrum/JR DSMx satellite receiver functions
* @brief Code to bind and read Spektrum/JR DSMx satellite receiver serial stream
* @{
*
* @file pios_dsm.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
* @brief Code bind and read Spektrum/JR DSMx satellite receiver serial stream
* @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"
#include "pios_dsm_priv.h"
#if defined(PIOS_INCLUDE_DSM)
/* Forward Declarations */
static int32_t PIOS_DSM_Get(uint32_t rcvr_id, uint8_t channel);
static uint16_t PIOS_DSM_RxInCallback(uint32_t context,
uint8_t *buf,
uint16_t buf_len,
uint16_t *headroom,
bool *need_yield);
static void PIOS_DSM_Supervisor(uint32_t dsm_id);
/* Local Variables */
const struct pios_rcvr_driver pios_dsm_rcvr_driver = {
.read = PIOS_DSM_Get,
};
enum pios_dsm_dev_magic {
PIOS_DSM_DEV_MAGIC = 0x44534d78,
};
struct pios_dsm_state {
uint16_t channel_data[PIOS_DSM_NUM_INPUTS];
uint8_t received_data[DSM_FRAME_LENGTH];
uint8_t receive_timer;
uint8_t failsafe_timer;
uint8_t frame_found;
uint8_t byte_count;
#ifdef DSM_LOST_FRAME_COUNTER
uint8_t frames_lost_last;
uint16_t frames_lost;
#endif
};
struct pios_dsm_dev {
enum pios_dsm_dev_magic magic;
const struct pios_dsm_cfg *cfg;
enum pios_dsm_proto proto;
struct pios_dsm_state state;
};
/* Allocate DSM device descriptor */
#if defined(PIOS_INCLUDE_FREERTOS)
static struct pios_dsm_dev *PIOS_DSM_Alloc(void)
{
struct pios_dsm_dev *dsm_dev;
dsm_dev = (struct pios_dsm_dev *)pvPortMalloc(sizeof(*dsm_dev));
if (!dsm_dev)
return NULL;
dsm_dev->magic = PIOS_DSM_DEV_MAGIC;
return dsm_dev;
}
#else
static struct pios_dsm_dev pios_dsm_devs[PIOS_DSM_MAX_DEVS];
static uint8_t pios_dsm_num_devs;
static struct pios_dsm_dev *PIOS_DSM_Alloc(void)
{
struct pios_dsm_dev *dsm_dev;
if (pios_dsm_num_devs >= PIOS_DSM_MAX_DEVS)
return NULL;
dsm_dev = &pios_dsm_devs[pios_dsm_num_devs++];
dsm_dev->magic = PIOS_DSM_DEV_MAGIC;
return dsm_dev;
}
#endif
/* Validate DSM device descriptor */
static bool PIOS_DSM_Validate(struct pios_dsm_dev *dsm_dev)
{
return (dsm_dev->magic == PIOS_DSM_DEV_MAGIC);
}
/* Try to bind DSMx satellite using specified number of pulses */
static void PIOS_DSM_Bind(struct pios_dsm_dev *dsm_dev, uint8_t bind)
{
const struct pios_dsm_cfg *cfg = dsm_dev->cfg;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = cfg->bind.init.GPIO_Pin;
GPIO_InitStructure.GPIO_Speed = cfg->bind.init.GPIO_Speed;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
/* just to limit bind pulses */
if (bind > 10)
bind = 10;
GPIO_Init(cfg->bind.gpio, &cfg->bind.init);
/* RX line, set high */
GPIO_SetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
/* on CC works up to 140ms, guess bind window is around 20-140ms after power up */
PIOS_DELAY_WaitmS(60);
for (int i = 0; i < bind ; i++) {
/* RX line, drive low for 120us */
GPIO_ResetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
PIOS_DELAY_WaituS(120);
/* RX line, drive high for 120us */
GPIO_SetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
PIOS_DELAY_WaituS(120);
}
/* RX line, set input and wait for data */
GPIO_Init(cfg->bind.gpio, &GPIO_InitStructure);
}
/* Reset channels in case of lost signal or explicit failsafe receiver flag */
static void PIOS_DSM_ResetChannels(struct pios_dsm_dev *dsm_dev)
{
struct pios_dsm_state *state = &(dsm_dev->state);
for (int i = 0; i < PIOS_DSM_NUM_INPUTS; i++) {
state->channel_data[i] = PIOS_RCVR_TIMEOUT;
}
}
/* Reset DSM receiver state */
static void PIOS_DSM_ResetState(struct pios_dsm_dev *dsm_dev)
{
struct pios_dsm_state *state = &(dsm_dev->state);
state->receive_timer = 0;
state->failsafe_timer = 0;
state->frame_found = 0;
#ifdef DSM_LOST_FRAME_COUNTER
state->frames_lost_last = 0;
state->frames_lost = 0;
#endif
PIOS_DSM_ResetChannels(dsm_dev);
}
/**
* Check and unroll complete frame data.
* \output 0 frame data accepted
* \output -1 frame error found
*/
static int PIOS_DSM_UnrollChannels(struct pios_dsm_dev *dsm_dev)
{
struct pios_dsm_state *state = &(dsm_dev->state);
uint8_t resolution;
#ifdef DSM_LOST_FRAME_COUNTER
/* increment the lost frame counter */
uint8_t frames_lost = state->received_data[0];
state->frames_lost += (frames_lost - state->frames_lost_last);
state->frames_lost_last = frames_lost;
#endif
/* check the frame type assuming master satellite stream */
uint8_t type = state->received_data[1];
switch (type) {
case 0x01:
case 0x02:
case 0x12:
/* DSM2, DSMJ stream */
if (dsm_dev->proto == PIOS_DSM_PROTO_DSM2) {
/* DSM2/DSMJ resolution is known from the header */
resolution = (type & DSM_DSM2_RES_MASK) ? 11 : 10;
} else {
/* DSMX resolution should explicitly be selected */
goto stream_error;
}
break;
case 0xA2:
case 0xB2:
/* DSMX stream */
if (dsm_dev->proto == PIOS_DSM_PROTO_DSMX10BIT) {
resolution = 10;
} else if (dsm_dev->proto == PIOS_DSM_PROTO_DSMX11BIT) {
resolution = 11;
} else {
/* DSMX resolution should explicitly be selected */
goto stream_error;
}
break;
default:
/* unknown yet data stream */
goto stream_error;
}
/* unroll channels */
uint8_t *s = &(state->received_data[2]);
uint16_t mask = (resolution == 10) ? 0x03ff : 0x07ff;
for (int i = 0; i < DSM_CHANNELS_PER_FRAME; i++) {
uint16_t word = ((uint16_t)s[0] << 8) | s[1];
s += 2;
/* skip empty channel slot */
if (word == 0xffff)
continue;
/* minimal data validation */
if ((i > 0) && (word & DSM_2ND_FRAME_MASK)) {
/* invalid frame data, ignore rest of the frame */
goto stream_error;
}
/* extract and save the channel value */
uint8_t channel_num = (word >> resolution) & 0x0f;
if (channel_num < PIOS_DSM_NUM_INPUTS)
state->channel_data[channel_num] = (word & mask);
}
#ifdef DSM_LOST_FRAME_COUNTER
/* put lost frames counter into the last channel for debugging */
state->channel_data[PIOS_DSM_NUM_INPUTS-1] = state->frames_lost;
#endif
/* all channels processed */
return 0;
stream_error:
/* either DSM2 selected with DSMX stream found, or vice-versa */
return -1;
}
/* Update decoder state processing input byte from the DSMx stream */
static void PIOS_DSM_UpdateState(struct pios_dsm_dev *dsm_dev, uint8_t byte)
{
struct pios_dsm_state *state = &(dsm_dev->state);
if (state->frame_found) {
/* receiving the data frame */
if (state->byte_count < DSM_FRAME_LENGTH) {
/* store next byte */
state->received_data[state->byte_count++] = byte;
if (state->byte_count == DSM_FRAME_LENGTH) {
/* full frame received - process and wait for new one */
if (!PIOS_DSM_UnrollChannels(dsm_dev))
/* data looking good */
state->failsafe_timer = 0;
/* prepare for the next frame */
state->frame_found = 0;
}
}
}
}
/* Initialise DSM receiver interface */
int32_t PIOS_DSM_Init(uint32_t *dsm_id,
const struct pios_dsm_cfg *cfg,
const struct pios_com_driver *driver,
uint32_t lower_id,
enum pios_dsm_proto proto,
uint8_t bind)
{
PIOS_DEBUG_Assert(dsm_id);
PIOS_DEBUG_Assert(cfg);
PIOS_DEBUG_Assert(driver);
struct pios_dsm_dev *dsm_dev;
dsm_dev = (struct pios_dsm_dev *)PIOS_DSM_Alloc();
if (!dsm_dev)
return -1;
/* Bind the configuration to the device instance */
dsm_dev->cfg = cfg;
dsm_dev->proto = proto;
/* Bind the receiver if requested */
if (bind)
PIOS_DSM_Bind(dsm_dev, bind);
PIOS_DSM_ResetState(dsm_dev);
*dsm_id = (uint32_t)dsm_dev;
/* Set comm driver callback */
(driver->bind_rx_cb)(lower_id, PIOS_DSM_RxInCallback, *dsm_id);
if (!PIOS_RTC_RegisterTickCallback(PIOS_DSM_Supervisor, *dsm_id)) {
PIOS_DEBUG_Assert(0);
}
return 0;
}
/* Comm byte received callback */
static uint16_t PIOS_DSM_RxInCallback(uint32_t context,
uint8_t *buf,
uint16_t buf_len,
uint16_t *headroom,
bool *need_yield)
{
struct pios_dsm_dev *dsm_dev = (struct pios_dsm_dev *)context;
bool valid = PIOS_DSM_Validate(dsm_dev);
PIOS_Assert(valid);
/* process byte(s) and clear receive timer */
for (uint8_t i = 0; i < buf_len; i++) {
PIOS_DSM_UpdateState(dsm_dev, buf[i]);
dsm_dev->state.receive_timer = 0;
}
/* Always signal that we can accept another byte */
if (headroom)
*headroom = DSM_FRAME_LENGTH;
/* We never need a yield */
*need_yield = false;
/* Always indicate that all bytes were consumed */
return buf_len;
}
/**
* Get the value of an input channel
* \param[in] channel Number of the channel desired (zero based)
* \output PIOS_RCVR_INVALID channel not available
* \output PIOS_RCVR_TIMEOUT failsafe condition or missing receiver
* \output >0 channel value
*/
static int32_t PIOS_DSM_Get(uint32_t rcvr_id, uint8_t channel)
{
struct pios_dsm_dev *dsm_dev = (struct pios_dsm_dev *)rcvr_id;
if (!PIOS_DSM_Validate(dsm_dev))
return PIOS_RCVR_INVALID;
/* return error if channel is not available */
if (channel >= PIOS_DSM_NUM_INPUTS)
return PIOS_RCVR_INVALID;
/* may also be PIOS_RCVR_TIMEOUT set by other function */
return dsm_dev->state.channel_data[channel];
}
/**
* Input data supervisor is called periodically and provides
* two functions: frame syncing and failsafe triggering.
*
* DSM frames come at 11ms or 22ms rate at 115200bps.
* RTC timer is running at 625Hz (1.6ms). So with divider 5 it gives
* 8ms pause between frames which is good for both DSM frame rates.
*
* Data receive function must clear the receive_timer to confirm new
* data reception. If no new data received in 100ms, we must call the
* failsafe function which clears all channels.
*/
static void PIOS_DSM_Supervisor(uint32_t dsm_id)
{
struct pios_dsm_dev *dsm_dev = (struct pios_dsm_dev *)dsm_id;
bool valid = PIOS_DSM_Validate(dsm_dev);
PIOS_Assert(valid);
struct pios_dsm_state *state = &(dsm_dev->state);
/* waiting for new frame if no bytes were received in 8ms */
if (++state->receive_timer > 4) {
state->frame_found = 1;
state->byte_count = 0;
state->receive_timer = 0;
}
/* activate failsafe if no frames have arrived in 102.4ms */
if (++state->failsafe_timer > 64) {
PIOS_DSM_ResetChannels(dsm_dev);
state->failsafe_timer = 0;
}
}
#endif /* PIOS_INCLUDE_DSM */
/**
* @}
* @}
*/

View File

@ -2,13 +2,13 @@
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SBUS Futaba S.Bus receiver functions
* @brief Code to read Futaba S.Bus input
* @addtogroup PIOS_SBus Futaba S.Bus receiver functions
* @brief Code to read Futaba S.Bus receiver serial stream
* @{
*
* @file pios_sbus.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
* @brief USART commands. Inits USARTs, controls USARTs & Interrupt handlers. (STM32 dependent)
* @brief Code to read Futaba S.Bus receiver serial stream
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
@ -34,44 +34,166 @@
#if defined(PIOS_INCLUDE_SBUS)
/* Provide a RCVR driver */
static int32_t PIOS_SBUS_Get(uint32_t rcvr_id, uint8_t channel);
/* Forward Declarations */
static int32_t PIOS_SBus_Get(uint32_t rcvr_id, uint8_t channel);
static uint16_t PIOS_SBus_RxInCallback(uint32_t context,
uint8_t *buf,
uint16_t buf_len,
uint16_t *headroom,
bool *need_yield);
static void PIOS_SBus_Supervisor(uint32_t sbus_id);
const struct pios_rcvr_driver pios_sbus_rcvr_driver = {
.read = PIOS_SBUS_Get,
};
/* Local Variables */
static uint16_t channel_data[SBUS_NUMBER_OF_CHANNELS];
static uint8_t received_data[SBUS_FRAME_LENGTH - 2];
static uint8_t receive_timer;
static uint8_t failsafe_timer;
static uint8_t frame_found;
const struct pios_rcvr_driver pios_sbus_rcvr_driver = {
.read = PIOS_SBus_Get,
};
static void PIOS_SBUS_Supervisor(uint32_t sbus_id);
enum pios_sbus_dev_magic {
PIOS_SBUS_DEV_MAGIC = 0x53427573,
};
/**
* reset_channels() function clears all channel data in case of
* lost signal or explicit failsafe flag from the S.Bus data stream
*/
static void reset_channels(void)
struct pios_sbus_state {
uint16_t channel_data[PIOS_SBUS_NUM_INPUTS];
uint8_t received_data[SBUS_FRAME_LENGTH - 2];
uint8_t receive_timer;
uint8_t failsafe_timer;
uint8_t frame_found;
uint8_t byte_count;
};
struct pios_sbus_dev {
enum pios_sbus_dev_magic magic;
const struct pios_sbus_cfg *cfg;
struct pios_sbus_state state;
};
/* Allocate S.Bus device descriptor */
#if defined(PIOS_INCLUDE_FREERTOS)
static struct pios_sbus_dev *PIOS_SBus_Alloc(void)
{
for (int i = 0; i < SBUS_NUMBER_OF_CHANNELS; i++) {
channel_data[i] = PIOS_RCVR_TIMEOUT;
struct pios_sbus_dev *sbus_dev;
sbus_dev = (struct pios_sbus_dev *)pvPortMalloc(sizeof(*sbus_dev));
if (!sbus_dev) return(NULL);
sbus_dev->magic = PIOS_SBUS_DEV_MAGIC;
return(sbus_dev);
}
#else
static struct pios_sbus_dev pios_sbus_devs[PIOS_SBUS_MAX_DEVS];
static uint8_t pios_sbus_num_devs;
static struct pios_sbus_dev *PIOS_SBus_Alloc(void)
{
struct pios_sbus_dev *sbus_dev;
if (pios_sbus_num_devs >= PIOS_SBUS_MAX_DEVS) {
return (NULL);
}
sbus_dev = &pios_sbus_devs[pios_sbus_num_devs++];
sbus_dev->magic = PIOS_SBUS_DEV_MAGIC;
return (sbus_dev);
}
#endif
/* Validate S.Bus device descriptor */
static bool PIOS_SBus_Validate(struct pios_sbus_dev *sbus_dev)
{
return (sbus_dev->magic == PIOS_SBUS_DEV_MAGIC);
}
/* Reset channels in case of lost signal or explicit failsafe receiver flag */
static void PIOS_SBus_ResetChannels(struct pios_sbus_state *state)
{
for (int i = 0; i < PIOS_SBUS_NUM_INPUTS; i++) {
state->channel_data[i] = PIOS_RCVR_TIMEOUT;
}
}
/* Reset S.Bus receiver state */
static void PIOS_SBus_ResetState(struct pios_sbus_state *state)
{
state->receive_timer = 0;
state->failsafe_timer = 0;
state->frame_found = 0;
PIOS_SBus_ResetChannels(state);
}
/* Initialise S.Bus receiver interface */
int32_t PIOS_SBus_Init(uint32_t *sbus_id,
const struct pios_sbus_cfg *cfg,
const struct pios_com_driver *driver,
uint32_t lower_id)
{
PIOS_DEBUG_Assert(sbus_id);
PIOS_DEBUG_Assert(cfg);
PIOS_DEBUG_Assert(driver);
struct pios_sbus_dev *sbus_dev;
sbus_dev = (struct pios_sbus_dev *)PIOS_SBus_Alloc();
if (!sbus_dev) goto out_fail;
/* Bind the configuration to the device instance */
sbus_dev->cfg = cfg;
PIOS_SBus_ResetState(&(sbus_dev->state));
*sbus_id = (uint32_t)sbus_dev;
/* Enable inverter clock and enable the inverter */
(*cfg->gpio_clk_func)(cfg->gpio_clk_periph, ENABLE);
GPIO_Init(cfg->inv.gpio, &cfg->inv.init);
GPIO_WriteBit(cfg->inv.gpio, cfg->inv.init.GPIO_Pin, cfg->gpio_inv_enable);
/* Set comm driver callback */
(driver->bind_rx_cb)(lower_id, PIOS_SBus_RxInCallback, *sbus_id);
if (!PIOS_RTC_RegisterTickCallback(PIOS_SBus_Supervisor, *sbus_id)) {
PIOS_DEBUG_Assert(0);
}
return 0;
out_fail:
return -1;
}
/**
* unroll_channels() function computes channel_data[] from received_data[]
* Get the value of an input channel
* \param[in] channel Number of the channel desired (zero based)
* \output PIOS_RCVR_INVALID channel not available
* \output PIOS_RCVR_TIMEOUT failsafe condition or missing receiver
* \output >0 channel value
*/
static int32_t PIOS_SBus_Get(uint32_t rcvr_id, uint8_t channel)
{
struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)rcvr_id;
if (!PIOS_SBus_Validate(sbus_dev))
return PIOS_RCVR_INVALID;
/* return error if channel is not available */
if (channel >= PIOS_SBUS_NUM_INPUTS) {
return PIOS_RCVR_INVALID;
}
return sbus_dev->state.channel_data[channel];
}
/**
* Compute channel_data[] from received_data[].
* For efficiency it unrolls first 8 channels without loops and does the
* same for other 8 channels. Also 2 discrete channels will be set.
*/
static void unroll_channels(void)
static void PIOS_SBus_UnrollChannels(struct pios_sbus_state *state)
{
uint8_t *s = received_data;
uint16_t *d = channel_data;
uint8_t *s = state->received_data;
uint16_t *d = state->channel_data;
#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);
@ -98,132 +220,119 @@ static void unroll_channels(void)
*d++ = (s[22] & SBUS_FLAG_DC2) ? SBUS_VALUE_MAX : SBUS_VALUE_MIN;
}
/**
* process_byte() function processes incoming byte from S.Bus stream
*/
static void process_byte(uint8_t b)
/* Update decoder state processing input byte from the S.Bus stream */
static void PIOS_SBus_UpdateState(struct pios_sbus_state *state, uint8_t b)
{
static uint8_t byte_count;
/* should not process any data until new frame is found */
if (!state->frame_found)
return;
if (frame_found == 0) {
/* no frame found yet, waiting for start byte */
if (b == SBUS_SOF_BYTE) {
byte_count = 0;
frame_found = 1;
}
} else {
/* do not store start and end of frame bytes */
if (byte_count < SBUS_FRAME_LENGTH - 2) {
/* store next byte */
received_data[byte_count++] = b;
if (state->byte_count == 0) {
if (b != SBUS_SOF_BYTE) {
/* discard the whole frame if the 1st byte is not correct */
state->frame_found = 0;
} else {
if (b == SBUS_EOF_BYTE) {
/* full frame received */
uint8_t flags = received_data[SBUS_FRAME_LENGTH - 3];
if (flags & SBUS_FLAG_FL) {
/* frame lost, do not update */
} else if (flags & SBUS_FLAG_FS) {
/* failsafe flag active */
reset_channels();
} else {
/* data looking good */
unroll_channels();
failsafe_timer = 0;
}
} else {
/* discard whole frame */
}
/* prepare for the next frame */
frame_found = 0;
/* do not store the SOF byte */
state->byte_count++;
}
return;
}
/* do not store last frame byte as well */
if (state->byte_count < SBUS_FRAME_LENGTH - 1) {
/* store next byte */
state->received_data[state->byte_count - 1] = b;
state->byte_count++;
} else {
if (b == SBUS_EOF_BYTE) {
/* full frame received */
uint8_t flags = state->received_data[SBUS_FRAME_LENGTH - 3];
if (flags & SBUS_FLAG_FL) {
/* frame lost, do not update */
} else if (flags & SBUS_FLAG_FS) {
/* failsafe flag active */
PIOS_SBus_ResetChannels(state);
} else {
/* data looking good */
PIOS_SBus_UnrollChannels(state);
state->failsafe_timer = 0;
}
} else {
/* discard whole frame */
}
/* prepare for the next frame */
state->frame_found = 0;
}
}
static uint16_t PIOS_SBUS_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
/* Comm byte received callback */
static uint16_t PIOS_SBus_RxInCallback(uint32_t context,
uint8_t *buf,
uint16_t buf_len,
uint16_t *headroom,
bool *need_yield)
{
struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)context;
bool valid = PIOS_SBus_Validate(sbus_dev);
PIOS_Assert(valid);
struct pios_sbus_state *state = &(sbus_dev->state);
/* process byte(s) and clear receive timer */
for (uint8_t i = 0; i < buf_len; i++) {
process_byte(buf[i]);
receive_timer = 0;
PIOS_SBus_UpdateState(state, buf[i]);
state->receive_timer = 0;
}
/* Always signal that we can accept another byte */
if (headroom) {
if (headroom)
*headroom = SBUS_FRAME_LENGTH;
}
/* We never need a yield */
*need_yield = false;
/* Always indicate that all bytes were consumed */
return (buf_len);
}
/**
* Initialise S.Bus receiver interface
*/
int32_t PIOS_SBUS_Init(uint32_t * sbus_id, const struct pios_sbus_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id)
{
/* Enable inverter clock and enable the inverter */
(*cfg->gpio_clk_func)(cfg->gpio_clk_periph, ENABLE);
GPIO_Init(cfg->inv.gpio, &cfg->inv.init);
GPIO_WriteBit(cfg->inv.gpio,
cfg->inv.init.GPIO_Pin,
cfg->gpio_inv_enable);
(driver->bind_rx_cb)(lower_id, PIOS_SBUS_RxInCallback, 0);
if (!PIOS_RTC_RegisterTickCallback(PIOS_SBUS_Supervisor, 0)) {
PIOS_Assert(0);
}
return (0);
}
/**
* Get the value of an input channel
* \param[in] channel Number of the channel desired (zero based)
* \output -1 channel not available
* \output >0 channel value
*/
static int32_t PIOS_SBUS_Get(uint32_t rcvr_id, uint8_t channel)
{
/* return error if channel is not available */
if (channel >= SBUS_NUMBER_OF_CHANNELS) {
return PIOS_RCVR_INVALID;
}
return channel_data[channel];
return buf_len;
}
/**
* Input data supervisor is called periodically and provides
* two functions: frame syncing and failsafe triggering.
*
* S.Bus frames come at 7ms (HS) or 14ms (FS) rate at 100000bps. RTC
* timer is running at 625Hz (1.6ms). So with divider 2 it gives
* 3.2ms pause between frames which is good for both S.Bus data rates.
* S.Bus frames come at 7ms (HS) or 14ms (FS) rate at 100000bps.
* RTC timer is running at 625Hz (1.6ms). So with divider 2 it gives
* 3.2ms pause between frames which is good for both S.Bus frame rates.
*
* Data receive function must clear the receive_timer to confirm new
* data reception. If no new data received in 100ms, we must call the
* failsafe function which clears all channels.
*/
static void PIOS_SBUS_Supervisor(uint32_t sbus_id)
static void PIOS_SBus_Supervisor(uint32_t sbus_id)
{
struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)sbus_id;
bool valid = PIOS_SBus_Validate(sbus_dev);
PIOS_Assert(valid);
struct pios_sbus_state *state = &(sbus_dev->state);
/* waiting for new frame if no bytes were received in 3.2ms */
if (++receive_timer > 2) {
receive_timer = 0;
frame_found = 0;
if (++state->receive_timer > 2) {
state->frame_found = 1;
state->byte_count = 0;
state->receive_timer = 0;
}
/* activate failsafe if no frames have arrived in 102.4ms */
if (++failsafe_timer > 64) {
reset_channels();
failsafe_timer = 0;
if (++state->failsafe_timer > 64) {
PIOS_SBus_ResetChannels(state);
state->failsafe_timer = 0;
}
}
#endif
#endif /* PIOS_INCLUDE_SBUS */
/**
* @}

View File

@ -1,350 +0,0 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SPEKTRUM Spektrum receiver functions
* @brief Code to read Spektrum input
* @{
*
* @file pios_spektrum.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief USART commands. Inits USARTs, controls USARTs & Interrupt handlers. (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_SPEKTRUM)
#include "pios_spektrum_priv.h"
/**
* @Note Framesyncing:
* The code resets the watchdog timer whenever a single byte is received, so what watchdog code
* is never called if regularly getting bytes.
* RTC timer is running @625Hz, supervisor timer has divider 5 so frame sync comes every 1/125Hz=8ms.
* Good for both 11ms and 22ms framecycles
*/
/* Global Variables */
/* Provide a RCVR driver */
static int32_t PIOS_SPEKTRUM_Get(uint32_t rcvr_id, uint8_t channel);
const struct pios_rcvr_driver pios_spektrum_rcvr_driver = {
.read = PIOS_SPEKTRUM_Get,
};
enum pios_spektrum_dev_magic {
PIOS_SPEKTRUM_DEV_MAGIC = 0xa9b9c9d9,
};
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 bool PIOS_SPEKTRUM_Bind(const struct pios_spektrum_cfg * cfg, uint8_t bind);
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)
{
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 */
for (uint8_t i = 0; i < buf_len; i++) {
PIOS_SPEKTRUM_UpdateFSM(&(spektrum_dev->fsm), buf[i]);
spektrum_dev->supv_timer = 0;
}
/* Always signal that we can accept another byte */
if (headroom) {
*headroom = 1;
}
/* We never need a yield */
*need_yield = false;
/* Always indicate that all bytes were consumed */
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
*/
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)
{
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) {
PIOS_SPEKTRUM_Bind(cfg,bind);
}
PIOS_SPEKTRUM_ResetFSM(&(spektrum_dev->fsm));
*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);
}
return (0);
out_fail:
return(-1);
}
/**
* Get the value of an input channel
* \param[in] Channel Number of the channel desired
* \output -1 Channel not available
* \output >0 Channel value
*/
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 */
if (channel >= PIOS_SPEKTRUM_NUM_INPUTS) {
return PIOS_RCVR_INVALID;
}
return spektrum_dev->fsm.CaptureValue[channel];
}
/**
* Spektrum bind function
* \output true Successful bind
* \output false Bind failed
*/
static bool PIOS_SPEKTRUM_Bind(const struct pios_spektrum_cfg * cfg, uint8_t bind)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = cfg->bind.init.GPIO_Pin;
GPIO_InitStructure.GPIO_Speed = cfg->bind.init.GPIO_Speed;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
/* just to limit bind pulses */
bind=(bind<=10)?bind:10;
GPIO_Init(cfg->bind.gpio, &cfg->bind.init);
/* RX line, set high */
GPIO_SetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
/* on CC works upto 140ms, I guess bind window is around 20-140ms after powerup */
PIOS_DELAY_WaitmS(60);
for (int i = 0; i < bind ; i++) {
/* RX line, drive low for 120us */
GPIO_ResetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
PIOS_DELAY_WaituS(120);
/* RX line, drive high for 120us */
GPIO_SetBits(cfg->bind.gpio, cfg->bind.init.GPIO_Pin);
PIOS_DELAY_WaituS(120);
}
/* RX line, set input and wait for data, PIOS_SPEKTRUM_Init */
GPIO_Init(cfg->bind.gpio, &GPIO_InitStructure);
return true;
}
/**
*@brief This function is called between frames and when a spektrum word hasnt been decoded for too long
*@brief clears the channel values
*/
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 */
spektrum_dev->supv_timer++;
if(spektrum_dev->supv_timer > 4) {
/* sync between frames */
struct pios_spektrum_fsm * fsm = &(spektrum_dev->fsm);
fsm->sync = 0;
fsm->bytecount = 0;
fsm->prev_byte = 0xFF;
fsm->frame_error = 0;
fsm->sync_of++;
/* watchdog activated after 200ms silence */
if (fsm->sync_of > 30) {
/* signal lost */
fsm->sync_of = 0;
for (int i = 0; i < PIOS_SPEKTRUM_NUM_INPUTS; i++) {
fsm->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
fsm->CaptureValueTemp[i] = PIOS_RCVR_TIMEOUT;
}
}
spektrum_dev->supv_timer = 0;
}
}
#endif
/**
* @}
* @}
*/

View File

@ -2,13 +2,12 @@
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SPEKTRUM Spektrum receiver functions
* @addtogroup PIOS_DSM Spektrum/JR DSMx satellite receiver functions
* @{
*
* @file pios_spektrum.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Thorsten Klose (tk@midibox.org)
* @brief Spektrum satellite functions header.
* @file pios_dsm.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
* @brief Spektrum/JR DSMx satellite receiver functions header.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
@ -28,16 +27,16 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PIOS_SPEKTRUM_H
#define PIOS_SPEKTRUM_H
#ifndef PIOS_DSM_H
#define PIOS_DSM_H
/* Global Types */
/* Public Functions */
#endif /* PIOS_SPEKTRUM_H */
#endif /* PIOS_DSM_H */
/**
* @}
* @}
*/
* @}
* @}
*/

View File

@ -0,0 +1,139 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_DSM Spektrum/JR DSMx satellite receiver functions
* @brief PIOS interface to bind and read Spektrum/JR DSMx satellite receiver
* @{
*
* @file pios_dsm_priv.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
* @brief Spektrum/JR DSMx satellite receiver private structures.
* @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_DSM_PRIV_H
#define PIOS_DSM_PRIV_H
#include <pios.h>
#include <pios_stm32.h>
#include <pios_usart_priv.h>
/*
* Currently known DSMx (DSM2, DSMJ, DSMX) satellite serial port settings:
* 115200bps serial stream, 8 bits, no parity, 1 stop bit
* size of each frame: 16 bytes
* data resolution: 10 or 11 bits
* number of frames: 1 or 2
* frame period: 11ms or 22ms
*
* Currently known DSMx frame structure:
* 2 bytes - depend on protocol version:
* for DSM2/DSMJ:
* 1 byte - lost frame counter (8 bit)
* 1 byte - data format (for master receiver bound with 3 or 5 pulses),
* or unknown (for slave receiver bound with 4 or 6 pulses,
* some sources call it also the lost frame counter)
* for DSMX:
* 1 byte - unknown data (does not look like lost frame counter)
* 1 byte - unknown data, has been seen only 0xB2 so far
* 14 bytes - up to 7 channels (16 bit word per channel) with encoded channel
* number, channel value, the "2nd frame in a sequence" flag.
* Unused channels have FF FF instead of data bytes.
*
* Data format identification:
* - for DSM2/DSMJ: [0 0 0 R 0 0 N1 N0]
* where
* R is data resolution (0 - 10 bits, 1 - 11 bits),
* N1..N0 is the number of frames required to receive all channel
* data (01 or 10 are known to the moment, which means 1 or 2 frames).
* Three values for the transmitter information byte have been seen
* thus far: 0x01, 0x02, 0x12.
* - for DSMX this byte contains just 0xB2 or 0xA2 value for any resolution.
* It is not known at the moment how to find the exact resolution from the
* DSMX data stream. The frame number (1 or 2) and 10/11 bit resolution were
* found in different data streams. So it is safer at the moment to ask user
* explicitly choose the resolution.
* Also some weird throttle channel (0) behavior was found in some streams
* from DX8 transmitter (all zeroes). Thus DSMX needs special processing.
*
* Channel data are:
* - for 10 bit: [F 0 C3 C2 C1 C0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
* - for 11 bit: [F C3 C2 C1 C0 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
* where
* F is normally 0 but set to 1 for the first channel of the 2nd frame,
* C3 to C0 is the channel number, 4 bit, zero-based, in any order,
* Dx..D0 - channel data (10 or 11 bits)
*
* DSM2 protocol bug: in some cases in 2-frame format some bytes of the
* frame can contain invalid values from the previous frame. They usually
* are the last 5 bytes and can be equal to FF or other data from last
* frame. There is no explicit workaround currently known.
*
* Binding: the number of pulses within bind window after power up defines
* if this receiver is a master (provides receiver capabilities info to
* the transmitter to choose data format) or slave (does not respond to
* the transmitter which falls back to the old DSM mode in that case).
* Currently known are 3(4) pulses for low resolution (10 bit) mode, and
* 5(6) pulses for high resolution (11 bit) mode. Thus only 3 or 5 pulses
* should be used for stand-alone satellite receiver to be bound correctly
* as the master. 5 pulses (high resolution) mode simulates high-end
* receivers which should work in all cases except user explicitly wants
* to bind in low resolution mode.
*/
#define DSM_CHANNELS_PER_FRAME 7
#define DSM_FRAME_LENGTH (1+1+DSM_CHANNELS_PER_FRAME*2)
#define DSM_DSM2_RES_MASK 0x0010
#define DSM_2ND_FRAME_MASK 0x8000
/*
* Include lost frame counter and provide it as a last channel value
* for debugging. Currently is not used by the receiver layer.
*/
//#define DSM_LOST_FRAME_COUNTER
/* DSM protocol variations */
enum pios_dsm_proto {
PIOS_DSM_PROTO_DSM2,
PIOS_DSM_PROTO_DSMX10BIT,
PIOS_DSM_PROTO_DSMX11BIT,
};
/* DSM receiver instance configuration */
struct pios_dsm_cfg {
struct stm32_gpio bind;
};
extern const struct pios_rcvr_driver pios_dsm_rcvr_driver;
extern int32_t PIOS_DSM_Init(uint32_t *dsm_id,
const struct pios_dsm_cfg *cfg,
const struct pios_com_driver *driver,
uint32_t lower_id,
enum pios_dsm_proto proto,
uint8_t bind);
#endif /* PIOS_DSM_PRIV_H */
/**
* @}
* @}
*/

View File

@ -2,7 +2,7 @@
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SBUS Futaba S.Bus receiver functions
* @addtogroup PIOS_SBus Futaba S.Bus receiver functions
* @{
*
* @file pios_sbus.h

View File

@ -2,7 +2,7 @@
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SBUS S.Bus Functions
* @addtogroup PIOS_SBus S.Bus Functions
* @brief PIOS interface to read and write from Futaba S.Bus port
* @{
*
@ -63,7 +63,9 @@
* S.Bus protocol provides 16 proportional and 2 discrete channels.
* Do not change unless driver code is updated accordingly.
*/
#define SBUS_NUMBER_OF_CHANNELS (16 + 2)
#if (PIOS_SBUS_NUM_INPUTS != (16+2))
#error "S.Bus protocol provides 16 proportional and 2 discrete channels"
#endif
/* Discrete channels represented as bits, provide values for them */
#define SBUS_VALUE_MIN 352
@ -81,7 +83,10 @@ struct pios_sbus_cfg {
extern const struct pios_rcvr_driver pios_sbus_rcvr_driver;
extern int32_t PIOS_SBUS_Init(uint32_t * sbus_id, const struct pios_sbus_cfg *cfg, const struct pios_com_driver * driver, uint32_t lower_id);
extern int32_t PIOS_SBus_Init(uint32_t *sbus_id,
const struct pios_sbus_cfg *cfg,
const struct pios_com_driver *driver,
uint32_t lower_id);
#endif /* PIOS_SBUS_PRIV_H */

View File

@ -1,52 +0,0 @@
/**
******************************************************************************
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_SPEKTRUM SPEKTRUM Functions
* @brief PIOS interface to read and write from spektrum port
* @{
*
* @file pios_spektrum_priv.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Servo private structures.
* @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_SPEKTRUM_PRIV_H
#define PIOS_SPEKTRUM_PRIV_H
#include <pios.h>
#include <pios_stm32.h>
#include <pios_usart_priv.h>
struct pios_spektrum_cfg {
struct stm32_gpio bind;
uint32_t remap; /* GPIO_Remap_* */
};
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);
#endif /* PIOS_SPEKTRUM_PRIV_H */
/**
* @}
* @}
*/

View File

@ -81,7 +81,7 @@
#include <pios_ppm.h>
#include <pios_pwm.h>
#include <pios_rcvr.h>
#include <pios_spektrum.h>
#include <pios_dsm.h>
#include <pios_sbus.h>
#include <pios_usb_hid.h>
#include <pios_debug.h>

View File

@ -96,11 +96,9 @@
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>"; };
65643CB01413322000A32F59 /* pios_dsm_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_dsm_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; };
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>"; };
@ -2658,7 +2656,6 @@
65C35E5612EFB2F3004811C2 /* attitudeactual.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = attitudeactual.xml; sourceTree = "<group>"; };
65C35E5812EFB2F3004811C2 /* attituderaw.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = attituderaw.xml; sourceTree = "<group>"; };
65C35E5912EFB2F3004811C2 /* baroaltitude.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = baroaltitude.xml; sourceTree = "<group>"; };
65C35E5A12EFB2F3004811C2 /* batterysettings.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = batterysettings.xml; sourceTree = "<group>"; };
65C35E5C12EFB2F3004811C2 /* flightbatterystate.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = flightbatterystate.xml; sourceTree = "<group>"; };
65C35E5D12EFB2F3004811C2 /* flightplancontrol.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = flightplancontrol.xml; sourceTree = "<group>"; };
65C35E5E12EFB2F3004811C2 /* flightplansettings.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = flightplansettings.xml; sourceTree = "<group>"; };
@ -2799,7 +2796,7 @@
65E8F04911EFF25C00BBF654 /* pios_pwm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_pwm.h; path = ../../PiOS/inc/pios_pwm.h; sourceTree = SOURCE_ROOT; };
65E8F04A11EFF25C00BBF654 /* pios_sdcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_sdcard.h; path = ../../PiOS/inc/pios_sdcard.h; sourceTree = SOURCE_ROOT; };
65E8F04B11EFF25C00BBF654 /* pios_servo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_servo.h; path = ../../PiOS/inc/pios_servo.h; sourceTree = SOURCE_ROOT; };
65E8F04C11EFF25C00BBF654 /* pios_spektrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_spektrum.h; path = ../../PiOS/inc/pios_spektrum.h; sourceTree = SOURCE_ROOT; };
65E8F04C11EFF25C00BBF654 /* pios_dsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_dsm.h; path = ../../PiOS/inc/pios_dsm.h; sourceTree = SOURCE_ROOT; };
65E8F04D11EFF25C00BBF654 /* pios_spi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_spi.h; path = ../../PiOS/inc/pios_spi.h; sourceTree = SOURCE_ROOT; };
65E8F04E11EFF25C00BBF654 /* pios_spi_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_spi_priv.h; path = ../../PiOS/inc/pios_spi_priv.h; sourceTree = SOURCE_ROOT; };
65E8F04F11EFF25C00BBF654 /* pios_stm32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pios_stm32.h; path = ../../PiOS/inc/pios_stm32.h; sourceTree = SOURCE_ROOT; };
@ -2928,7 +2925,7 @@
65E8F0E411EFF25C00BBF654 /* pios_ppm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_ppm.c; path = ../../PiOS/STM32F10x/pios_ppm.c; sourceTree = SOURCE_ROOT; };
65E8F0E511EFF25C00BBF654 /* pios_pwm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_pwm.c; path = ../../PiOS/STM32F10x/pios_pwm.c; sourceTree = SOURCE_ROOT; };
65E8F0E611EFF25C00BBF654 /* pios_servo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_servo.c; path = ../../PiOS/STM32F10x/pios_servo.c; sourceTree = SOURCE_ROOT; };
65E8F0E711EFF25C00BBF654 /* pios_spektrum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_spektrum.c; path = ../../PiOS/STM32F10x/pios_spektrum.c; sourceTree = SOURCE_ROOT; };
65E8F0E711EFF25C00BBF654 /* pios_dsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_dsm.c; path = ../../PiOS/STM32F10x/pios_dsm.c; sourceTree = SOURCE_ROOT; };
65E8F0E811EFF25C00BBF654 /* pios_spi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_spi.c; path = ../../PiOS/STM32F10x/pios_spi.c; sourceTree = SOURCE_ROOT; };
65E8F0E911EFF25C00BBF654 /* pios_sys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_sys.c; path = ../../PiOS/STM32F10x/pios_sys.c; sourceTree = SOURCE_ROOT; };
65E8F0EA11EFF25C00BBF654 /* pios_usart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pios_usart.c; path = ../../PiOS/STM32F10x/pios_usart.c; sourceTree = SOURCE_ROOT; };
@ -7436,7 +7433,6 @@
65C35E4F12EFB2F3004811C2 /* uavobjectdefinition */ = {
isa = PBXGroup;
children = (
65E6D80713E3A4D0002A557A /* hwsettings.xml */,
65E8C788139AA2A800E1F979 /* accessorydesired.xml */,
65C35E5012EFB2F3004811C2 /* actuatorcommand.xml */,
65C35E5112EFB2F3004811C2 /* actuatordesired.xml */,
@ -7448,7 +7444,6 @@
65C35E5812EFB2F3004811C2 /* attituderaw.xml */,
65E410AE12F65AEA00725888 /* attitudesettings.xml */,
65C35E5912EFB2F3004811C2 /* baroaltitude.xml */,
65C35E5A12EFB2F3004811C2 /* batterysettings.xml */,
655B1A8E13B2FC0900B0E48D /* camerastabsettings.xml */,
652C8568132B632A00BFCC70 /* firmwareiapobj.xml */,
65C35E5C12EFB2F3004811C2 /* flightbatterystate.xml */,
@ -7463,6 +7458,7 @@
65C35E6412EFB2F3004811C2 /* gpstime.xml */,
65C35E6512EFB2F3004811C2 /* guidancesettings.xml */,
65C35E6612EFB2F3004811C2 /* homelocation.xml */,
65E6D80713E3A4D0002A557A /* hwsettings.xml */,
65C35E6712EFB2F3004811C2 /* i2cstats.xml */,
65C35E6812EFB2F3004811C2 /* manualcontrolcommand.xml */,
65C35E6912EFB2F3004811C2 /* manualcontrolsettings.xml */,
@ -7743,8 +7739,8 @@
65E8F04A11EFF25C00BBF654 /* pios_sdcard.h */,
65E8F04B11EFF25C00BBF654 /* pios_servo.h */,
65FBE14412E7C98100176B5A /* pios_servo_priv.h */,
65E8F04C11EFF25C00BBF654 /* pios_spektrum.h */,
65643CB01413322000A32F59 /* pios_spektrum_priv.h */,
65E8F04C11EFF25C00BBF654 /* pios_dsm.h */,
65643CB01413322000A32F59 /* pios_dsm_priv.h */,
65E8F04D11EFF25C00BBF654 /* pios_spi.h */,
65E8F04E11EFF25C00BBF654 /* pios_spi_priv.h */,
65E8F04F11EFF25C00BBF654 /* pios_stm32.h */,
@ -7768,24 +7764,8 @@
65E8F05811EFF25C00BBF654 /* STM32F10x */ = {
isa = PBXGroup;
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 */,
65E8F0D811EFF25C00BBF654 /* link_stm32f10x_HD.ld */,
65E8F0DB11EFF25C00BBF654 /* link_stm32f10x_MD.ld */,
@ -7802,7 +7782,7 @@
6589A9DB131DEE76006BD67C /* pios_rtc.c */,
65643CBA141350C200A32F59 /* pios_sbus.c */,
65E8F0E611EFF25C00BBF654 /* pios_servo.c */,
65E8F0E711EFF25C00BBF654 /* pios_spektrum.c */,
65E8F0E711EFF25C00BBF654 /* pios_dsm.c */,
65E8F0E811EFF25C00BBF654 /* pios_spi.c */,
65E8F0E911EFF25C00BBF654 /* pios_sys.c */,
65643CB91413456D00A32F59 /* pios_tim.c */,

View File

@ -64,6 +64,7 @@ typedef struct {
uint32_t objId;
uint16_t instId;
uint32_t length;
uint8_t instanceLength;
uint8_t cs;
int32_t rxCount;
UAVTalkRxState state;

View File

@ -351,9 +351,15 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx
// Determine data length
if (iproc->type == UAVTALK_TYPE_OBJ_REQ || iproc->type == UAVTALK_TYPE_ACK || iproc->type == UAVTALK_TYPE_NACK)
{
iproc->length = 0;
iproc->instanceLength = 0;
}
else
{
iproc->length = UAVObjGetNumBytes(iproc->obj);
iproc->instanceLength = (UAVObjIsSingleInstance(iproc->obj) ? 0 : 2);
}
// Check length and determine next state
if (iproc->length >= UAVTALK_MAX_PAYLOAD_LENGTH)
@ -364,7 +370,7 @@ int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rx
}
// Check the lengths match
if ((iproc->rxPacketLength + iproc->length) != iproc->packet_size)
if ((iproc->rxPacketLength + iproc->instanceLength + iproc->length) != iproc->packet_size)
{ // packet error - mismatched packet size
connection->stats.rxErrors++;
iproc->state = UAVTALK_STATE_SYNC;

View File

@ -138,46 +138,6 @@
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 1</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 2</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 3</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 4</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 5</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 6</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 7</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 8</string>
</property>
</item>
</widget>
</item>
<item row="4" column="1">
@ -187,46 +147,6 @@
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 1</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 2</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 3</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 4</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 5</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 6</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 7</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 8</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
@ -243,46 +163,6 @@
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 1</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 2</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 3</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 4</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 5</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 6</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 7</string>
</property>
</item>
<item>
<property name="text">
<string>Channel 8</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
@ -323,6 +203,13 @@
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="message">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@ -25,6 +25,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config_cc_hw_widget.h"
#include "hwsettings.h"
#include <QDebug>
#include <QStringList>
@ -63,10 +64,13 @@ void ConfigCCHWWidget::refreshValues()
void ConfigCCHWWidget::widgetsContentsChanged()
{
ConfigTaskWidget::widgetsContentsChanged();
enableControls(false);
if((m_telemetry->cbFlexi->currentText()==m_telemetry->cbTele->currentText()) && m_telemetry->cbTele->currentText()!="Disabled")
if (((m_telemetry->cbTele->currentIndex() == HwSettings::CC_MAINPORT_TELEMETRY) && (m_telemetry->cbFlexi->currentIndex() == HwSettings::CC_FLEXIPORT_TELEMETRY)) ||
((m_telemetry->cbTele->currentIndex() == HwSettings::CC_MAINPORT_GPS) && (m_telemetry->cbFlexi->currentIndex() == HwSettings::CC_FLEXIPORT_GPS)) ||
((m_telemetry->cbTele->currentIndex() == HwSettings::CC_MAINPORT_COMAUX) && (m_telemetry->cbFlexi->currentIndex() == HwSettings::CC_FLEXIPORT_COMAUX)))
{
m_telemetry->problems->setText("Warning: you have configured the MainPort and the FlexiPort for the same function, this is currently not suported");
enableControls(false);
m_telemetry->problems->setText(tr("Warning: you have configured both MainPort and FlexiPort for the same function, this currently is not supported"));
}
else
{
@ -84,4 +88,3 @@ void ConfigCCHWWidget::openHelp()
* @}
* @}
*/

View File

@ -105,10 +105,13 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
ffTuningInProgress = false;
ffTuningPhase = false;
mixerTypes << "Mixer1Type" << "Mixer2Type" << "Mixer3Type"
<< "Mixer4Type" << "Mixer5Type" << "Mixer6Type" << "Mixer7Type" << "Mixer8Type";
mixerVectors << "Mixer1Vector" << "Mixer2Vector" << "Mixer3Vector"
<< "Mixer4Vector" << "Mixer5Vector" << "Mixer6Vector" << "Mixer7Vector" << "Mixer8Vector";
QStringList channels;
channels << "None";
for (int i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
mixerTypes << QString("Mixer%1Type").arg(i+1);
mixerVectors << QString("Mixer%1Vector").arg(i+1);
channels << QString("Channel%1").arg(i+1);
}
QStringList airframeTypes;
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Custom";
@ -124,11 +127,6 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
<< "Octo Coax X" << "Hexacopter Y6" << "Tricopter Y";
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
QStringList channels;
channels << "None" << "Channel1" << "Channel2" << "Channel3" <<
"Channel4" << "Channel5" << "Channel6" << "Channel7" << "Channel8";
// Now load all the channel assignements for fixed wing
m_aircraft->fwElevator1Channel->addItems(channels);
m_aircraft->fwElevator2Channel->addItems(channels);

View File

@ -41,12 +41,26 @@
#include "camerastabsettings.h"
#include "hwsettings.h"
#include "mixersettings.h"
#include "actuatorcommand.h"
ConfigCameraStabilizationWidget::ConfigCameraStabilizationWidget(QWidget *parent) : ConfigTaskWidget(parent)
{
m_camerastabilization = new Ui_CameraStabilizationWidget();
m_camerastabilization->setupUi(this);
QComboBox * selectors[3] = {
m_camerastabilization->rollChannel,
m_camerastabilization->pitchChannel,
m_camerastabilization->yawChannel
};
for (int i = 0; i < 3; i++) {
selectors[i]->clear();
selectors[i]->addItem("None");
for (int j = 0; j < ActuatorCommand::CHANNEL_NUMELEM; j++)
selectors[i]->addItem(QString("Channel %1").arg(j+1));
}
connectUpdates();
// Connect buttons
@ -95,7 +109,7 @@ void ConfigCameraStabilizationWidget::applySettings()
// Update the mixer settings
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
const int NUM_MIXERS = 8;
const int NUM_MIXERS = 10;
QComboBox * selectors[3] = {
m_camerastabilization->rollChannel,
@ -114,8 +128,11 @@ void ConfigCameraStabilizationWidget::applySettings()
&mixerSettingsData.Mixer6Type,
&mixerSettingsData.Mixer7Type,
&mixerSettingsData.Mixer8Type,
&mixerSettingsData.Mixer9Type,
&mixerSettingsData.Mixer10Type,
};
m_camerastabilization->message->setText("");
for (int i = 0; i < 3; i++)
{
// Channel 1 is second entry, so becomes zero
@ -127,6 +144,7 @@ void ConfigCameraStabilizationWidget::applySettings()
// If the mixer channel already to something that isn't what we are
// about to set it to reset to none
selectors[i]->setCurrentIndex(0);
m_camerastabilization->message->setText("One of the channels is already assigned, reverted to none");
} else {
// Make sure no other channels have this output set
for (int j = 0; j < NUM_MIXERS; j++)
@ -188,7 +206,7 @@ void ConfigCameraStabilizationWidget::refreshValues()
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
const int NUM_MIXERS = 8;
const int NUM_MIXERS = 10;
QComboBox * selectors[3] = {
m_camerastabilization->rollChannel,
m_camerastabilization->pitchChannel,
@ -206,6 +224,8 @@ void ConfigCameraStabilizationWidget::refreshValues()
&mixerSettingsData.Mixer6Type,
&mixerSettingsData.Mixer7Type,
&mixerSettingsData.Mixer8Type,
&mixerSettingsData.Mixer9Type,
&mixerSettingsData.Mixer10Type,
};
for (int i = 0; i < 3; i++)

View File

@ -464,7 +464,7 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
case wizardIdentifyLimits:
{
dimOtherControls(false);
setTxMovement(moveAll);
setTxMovement(nothing);
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();
@ -474,6 +474,7 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step)
manualSettingsData.ChannelMax[i]=manualSettingsData.ChannelNeutral[i];
}
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
}
break;
case wizardIdentifyInverted:
@ -570,6 +571,7 @@ void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
break;
case wizardIdentifyLimits:
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits()));
disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks()));
manualSettingsObj->setData(manualSettingsData);
restoreMdata();
break;
@ -618,224 +620,6 @@ 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
*/
@ -849,12 +633,16 @@ void ConfigInputWidget::setChannel(int newChan)
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"))
if(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan).contains("Accessory")) {
m_config->wzNext->setEnabled(true);
m_config->wzText->setText(m_config->wzText->text() + tr(" or click next to skip this channel."));
} else
m_config->wzNext->setEnabled(false);
setMoveFromCommand(newChan);
currentChannelNum = newChan;
channelDetected = false;
}
/**
@ -907,6 +695,8 @@ void ConfigInputWidget::identifyControls()
receiverActivityData=receiverActivityObj->getData();
if(receiverActivityData.ActiveChannel==255)
return;
if(channelDetected)
return;
else
{
receiverActivityData=receiverActivityObj->getData();
@ -918,6 +708,7 @@ void ConfigInputWidget::identifyControls()
lastChannel.number=currentChannel.number;
if(!usedChannels.contains(lastChannel) && debounce>1)
{
channelDetected = true;
debounce=0;
usedChannels.append(lastChannel);
manualSettingsData=manualSettingsObj->getData();
@ -932,7 +723,7 @@ void ConfigInputWidget::identifyControls()
m_config->wzText->clear();
setTxMovement(nothing);
QTimer::singleShot(300, this, SLOT(wzNext()));
QTimer::singleShot(500, this, SLOT(wzNext()));
}
void ConfigInputWidget::identifyLimits()
@ -945,6 +736,7 @@ void ConfigInputWidget::identifyLimits()
if(manualSettingsData.ChannelMax[i]<manualCommandData.Channel[i])
manualSettingsData.ChannelMax[i]=manualCommandData.Channel[i];
}
manualSettingsObj->setData(manualSettingsData);
}
void ConfigInputWidget::setMoveFromCommand(int command)
{
@ -1368,6 +1160,8 @@ void ConfigInputWidget::updateCalibration()
void ConfigInputWidget::simpleCalibration(bool enable)
{
if (enable) {
m_config->configurationWizard->setEnabled(false);
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."));
@ -1392,6 +1186,8 @@ void ConfigInputWidget::simpleCalibration(bool enable)
connect(manualCommandObj, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(updateCalibration()));
} else {
m_config->configurationWizard->setEnabled(true);
manualCommandData = manualCommandObj->getData();
manualSettingsData = manualSettingsObj->getData();

View File

@ -81,6 +81,7 @@ private:
}lastChannel;
channelsStruct currentChannel;
QList<channelsStruct> usedChannels;
bool channelDetected;
QEventLoop * loop;
bool skipflag;

View File

@ -38,28 +38,32 @@
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include "actuatorcommand.h"
#include "systemalarms.h"
ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(parent)
{
m_config = new Ui_OutputWidget();
m_config->setupUi(this);
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
setupButtons(m_config->saveRCOutputToRAM,m_config->saveRCOutputToSD);
addUAVObject("ActuatorSettings");
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
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:
// NOTE: for historical reasons, we have objects below called ch0 to ch7, but the convention for OP is Channel 1 to Channel 8.
// NOTE: for historical reasons, we have objects below called ch0 to ch7, but the convention for OP is Channel 1 to Channel 8.
outLabels << m_config->ch0OutValue
<< m_config->ch1OutValue
<< m_config->ch2OutValue
<< m_config->ch3OutValue
<< m_config->ch4OutValue
<< m_config->ch5OutValue
<< m_config->ch6OutValue
<< m_config->ch7OutValue;
<< m_config->ch1OutValue
<< m_config->ch2OutValue
<< m_config->ch3OutValue
<< m_config->ch4OutValue
<< m_config->ch5OutValue
<< m_config->ch6OutValue
<< m_config->ch7OutValue
<< m_config->ch8OutValue
<< m_config->ch9OutValue;
outSliders << m_config->ch0OutSlider
<< m_config->ch1OutSlider
@ -68,7 +72,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
<< m_config->ch4OutSlider
<< m_config->ch5OutSlider
<< m_config->ch6OutSlider
<< m_config->ch7OutSlider;
<< m_config->ch7OutSlider
<< m_config->ch8OutSlider
<< m_config->ch9OutSlider;
outMin << m_config->ch0OutMin
<< m_config->ch1OutMin
@ -77,7 +83,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
<< m_config->ch4OutMin
<< m_config->ch5OutMin
<< m_config->ch6OutMin
<< m_config->ch7OutMin;
<< m_config->ch7OutMin
<< m_config->ch8OutMin
<< m_config->ch9OutMin;
outMax << m_config->ch0OutMax
<< m_config->ch1OutMax
@ -86,7 +94,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
<< m_config->ch4OutMax
<< m_config->ch5OutMax
<< m_config->ch6OutMax
<< m_config->ch7OutMax;
<< m_config->ch7OutMax
<< m_config->ch8OutMax
<< m_config->ch9OutMax;
reversals << m_config->ch0Rev
<< m_config->ch1Rev
@ -95,7 +105,9 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
<< m_config->ch4Rev
<< m_config->ch5Rev
<< m_config->ch6Rev
<< m_config->ch7Rev;
<< m_config->ch7Rev
<< m_config->ch8Rev
<< m_config->ch9Rev;
links << m_config->ch0Link
<< m_config->ch1Link
@ -104,15 +116,23 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
<< m_config->ch4Link
<< m_config->ch5Link
<< m_config->ch6Link
<< m_config->ch7Link;
<< m_config->ch7Link
<< m_config->ch8Link
<< m_config->ch9Link;
// Register for ActuatorSettings changes:
for (int i = 0; i < 8; i++) {
for (int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
connect(outMin[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
connect(outMax[i], SIGNAL(editingFinished()), this, SLOT(setChOutRange()));
connect(reversals[i], SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool)));
// Now connect the channel out sliders to our signal to send updates in test mode
connect(outSliders[i], SIGNAL(valueChanged(int)), this, SLOT(sendChannelTest(int)));
addWidget(outMin[i]);
addWidget(outMax[i]);
addWidget(reversals[i]);
addWidget(outSliders[i]);
addWidget(links[i]);
}
connect(m_config->channelOutTest, SIGNAL(toggled(bool)), this, SLOT(runChannelTests(bool)));
@ -134,39 +154,7 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren
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);
}
@ -215,6 +203,22 @@ void ConfigOutputWidget::linkToggled(bool state)
*/
void ConfigOutputWidget::runChannelTests(bool state)
{
SystemAlarms * systemAlarmsObj = SystemAlarms::GetInstance(getObjectManager());
SystemAlarms::DataFields systemAlarms = systemAlarmsObj->getData();
if(state && systemAlarms.Alarm[SystemAlarms::ALARM_ACTUATOR] != SystemAlarms::ALARM_OK) {
QMessageBox mbox;
mbox.setText(QString(tr("The actuator module is in an error state. This can also occur because there are no inputs. Please fix these before testing outputs.")));
mbox.setStandardButtons(QMessageBox::Ok);
mbox.exec();
// Unfortunately must cache this since callback will reoccur
accInitialData = ActuatorCommand::GetInstance(getObjectManager())->getMetadata();
m_config->channelOutTest->setChecked(false);
return;
}
// Confirm this is definitely what they want
if(state) {
QMessageBox mbox;
@ -229,11 +233,7 @@ void ConfigOutputWidget::runChannelTests(bool state)
}
}
qDebug() << "Running with state " << state;
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorCommand")));
ActuatorCommand * obj = ActuatorCommand::GetInstance(getObjectManager());
UAVObject::Metadata mdata = obj->getMetadata();
if (state)
{
@ -252,6 +252,9 @@ void ConfigOutputWidget::runChannelTests(bool state)
foreach (QSpinBox* box, outMax) {
box->setEnabled(false);
}
foreach (QCheckBox* box, reversals) {
box->setEnabled(false);
}
}
else
@ -263,6 +266,9 @@ void ConfigOutputWidget::runChannelTests(bool state)
foreach (QSpinBox* box, outMax) {
box->setEnabled(true);
}
foreach (QCheckBox* box, reversals) {
box->setEnabled(true);
}
}
obj->setMetadata(mdata);
@ -301,6 +307,12 @@ void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str)
case 7:
m_config->ch7Output->setText(str);
break;
case 8:
m_config->ch8Output->setText(str);
break;
case 9:
m_config->ch9Output->setText(str);
break;
}
}
@ -384,14 +396,8 @@ void ConfigOutputWidget::refreshWidgetsValues()
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
// Reset all channel assignements:
m_config->ch0Output->setText("-");
m_config->ch1Output->setText("-");
m_config->ch2Output->setText("-");
m_config->ch3Output->setText("-");
m_config->ch4Output->setText("-");
m_config->ch5Output->setText("-");
m_config->ch6Output->setText("-");
m_config->ch7Output->setText("-");
for (int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++)
outLabels[i]->setText("-");
// Get the channel assignements:
UAVDataObject * obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
@ -418,8 +424,8 @@ void ConfigOutputWidget::refreshWidgetsValues()
// CopterControl family
m_config->chBank1->setText("1-3");
m_config->chBank2->setText("4");
m_config->chBank3->setText("5");
m_config->chBank4->setText("6");
m_config->chBank3->setText("5,7-8");
m_config->chBank4->setText("6,9-10");
m_config->outputRate1->setEnabled(true);
m_config->outputRate2->setEnabled(true);
m_config->outputRate3->setEnabled(true);
@ -443,7 +449,7 @@ void ConfigOutputWidget::refreshWidgetsValues()
// Get Channel ranges:
for (int i=0;i<8;i++) {
for (int i=0;i<ActuatorCommand::CHANNEL_NUMELEM;i++) {
field = obj->getField(QString("ChannelMin"));
int minValue = field->getValue(i).toInt();
outMin[i]->setValue(minValue);
@ -462,7 +468,7 @@ void ConfigOutputWidget::refreshWidgetsValues()
}
field = obj->getField(QString("ChannelNeutral"));
for (int i=0; i<8; i++) {
for (int i=0; i<ActuatorCommand::CHANNEL_NUMELEM; i++) {
int value = field->getValue(i).toInt();
outSliders[i]->setValue(value);
outLabels[i]->setText(QString::number(value));
@ -483,17 +489,17 @@ void ConfigOutputWidget::updateObjectsFromWidgets()
// Now send channel ranges:
UAVObjectField * field = obj->getField(QString("ChannelMax"));
for (int i = 0; i < 8; i++) {
for (int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
field->setValue(outMax[i]->value(),i);
}
field = obj->getField(QString("ChannelMin"));
for (int i = 0; i < 8; i++) {
for (int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
field->setValue(outMin[i]->value(),i);
}
field = obj->getField(QString("ChannelNeutral"));
for (int i = 0; i < 8; i++) {
for (int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
field->setValue(outSliders[i]->value(),i);
}

View File

@ -85,8 +85,8 @@ void inputChannelForm::groupUpdated()
count = 8; // Need to make this 6 for CC
break;
case ManualControlSettings::CHANNELGROUPS_PPM:
case ManualControlSettings::CHANNELGROUPS_SPEKTRUM1:
case ManualControlSettings::CHANNELGROUPS_SPEKTRUM2:
case ManualControlSettings::CHANNELGROUPS_DSMMAINPORT:
case ManualControlSettings::CHANNELGROUPS_DSMFLEXIPORT:
count = 12;
break;
case ManualControlSettings::CHANNELGROUPS_SBUS:

View File

@ -970,6 +970,172 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="actuator8Label">
<property name="text">
<string>Channel 9:</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="actuator9Label">
<property name="text">
<string>Channel 10:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="ch8Output">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>-</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="ch9Output">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>-</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QSpinBox" name="ch8OutMin">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QSpinBox" name="ch9OutMin">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="9" column="3">
<widget class="QSlider" name="ch8OutSlider">
<property name="maximum">
<number>9999</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="3">
<widget class="QSlider" name="ch9OutSlider">
<property name="maximum">
<number>9999</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QSpinBox" name="ch8OutMax">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="10" column="4">
<widget class="QSpinBox" name="ch9OutMax">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="9" column="5">
<widget class="QLabel" name="ch8OutValue">
<property name="text">
<string>0000</string>
</property>
</widget>
</item>
<item row="10" column="5">
<widget class="QLabel" name="ch9OutValue">
<property name="text">
<string>0000</string>
</property>
</widget>
</item>
<item row="9" column="6">
<widget class="QCheckBox" name="ch8Rev">
<property name="font">
<font>
<family>FreeSans</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Check to invert the channel.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="6">
<widget class="QCheckBox" name="ch9Rev">
<property name="font">
<font>
<family>FreeSans</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'FreeSans'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Check to invert the channel.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="7">
<widget class="QCheckBox" name="ch8Link">
<property name="toolTip">
<string>Only used with Test Output mode</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="7">
<widget class="QCheckBox" name="ch9Link">
<property name="toolTip">
<string>Only used with Test Output mode</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@ -2,7 +2,7 @@ TEMPLATE = lib
TARGET = DebugGadget
include(../../openpilotgcsplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../libs/libqxt/core/logengines.pri)
HEADERS += debugplugin.h \
debugengine.h

View File

@ -19,10 +19,9 @@ plugin_emptygadget.subdir = emptygadget
plugin_emptygadget.depends = plugin_coreplugin
SUBDIRS += plugin_emptygadget
# UAV Settings Import/Export plugin
# Debug Gadget plugin
plugin_debuggadget.subdir = debuggadget
#plugin_debughelper.depends = plugin_coreplugin
#plugin_debughelper.depends += plugin_uavobjects
plugin_debuggadget.depends = plugin_coreplugin
SUBDIRS += plugin_debuggadget
# Welcome plugin

View File

@ -1,58 +1,65 @@
function [] = OPLogConvert()
%% Define indices and arrays of structures to hold data
%% Define indices and arrays of structures to hold data
% THIS FILE IS AUTOMATICALLY GENERATED.
$(ALLOCATIONCODE)
%% Open file
%fid = fopen('log.opl');
[FileName,PathName,FilterIndex] = uigetfile('*.opl');
logfile = strcat(PathName,FileName);
fid = fopen(logfile);
while (1)
%% Read logging header
timestamp = fread(fid, 1, 'uint32');
if (feof(fid)); break; end
datasize = fread(fid, 1, 'int64');
%% Read message header
% get sync field (0x3C, 1 byte)
sync = fread(fid, 1, 'uint8');
if sync ~= hex2dec('3C')
disp ('Wrong sync byte');
return
end
% get msg type (quint8 1 byte ) should be 0x20, ignore the rest?
msgType = fread(fid, 1, 'uint8');
if msgType ~= hex2dec('20')
disp ('Wrong msgType');
return
end
% get msg size (quint16 2 bytes) excludes crc, include msg header and data payload
msgSize = fread(fid, 1, 'uint16');
% get obj id (quint32 4 bytes)
objID = fread(fid, 1, 'uint32');
%% Read object
switch objID
$(SWITCHCODE)
otherwise
disp('Unknown object ID');
msgBytesLeft = datasize - 1 - 1 - 2 - 4;
fread(fid, msgBytesLeft, 'uint8');
end
end
%% Clean Up and Save mat file
fclose(fid);
matfile = strrep(logfile,'opl','mat');
save(matfile $(SAVEOBJECTSCODE));
%% Open log file
% [FileName,PathName,FilterIndex] = uigetfile('*.opl');
FileName='OP-2011-10-22_22-27-09.opl';
PathName='/Users/kenz/Movies/brisk_videos/rover_test_1/';
FilterIndex=1;
logfile = fullfile(PathName,FileName);
fid = fopen(logfile);
% Parse log file, entry by entry
while (1)
%% Read logging header
timestamp = fread(fid, 1, 'uint32');
if (feof(fid)); break; end
datasize = fread(fid, 1, 'int64');
%% Read message header
% get sync field (0x3C, 1 byte)
sync = fread(fid, 1, 'uint8');
if sync ~= hex2dec('3C')
disp ('Wrong sync byte');
return
end
% get msg type (quint8 1 byte ) should be 0x20, ignore the rest?
msgType = fread(fid, 1, 'uint8');
if msgType ~= hex2dec('20')
disp ('Wrong msgType');
return
end
% get msg size (quint16 2 bytes) excludes crc, include msg header and data payload
msgSize = fread(fid, 1, 'uint16');
% get obj id (quint32 4 bytes)
objID = fread(fid, 1, 'uint32');
%% Read object
switch objID
$(SWITCHCODE)
otherwise
disp(['Unknown object ID: 0x' dec2hex(objID)]);
msgBytesLeft = datasize - 1 - 1 - 2 - 4;
fread(fid, msgBytesLeft, 'uint8');
end
end
%% Clean Up and Save mat file
fclose(fid);
matfile = strrep(logfile,'opl','mat');
save(matfile $(SAVEOBJECTSCODE));
%% Object reading functions
$(FUNCTIONSCODE)

View File

@ -282,9 +282,15 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
// Determine data length
if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK || rxType == TYPE_NACK)
{
rxLength = 0;
rxInstanceLength = 0;
}
else
{
rxLength = rxObj->getNumBytes();
rxInstanceLength = (rxObj->isSingleInstance() ? 0 : 2);
}
// Check length and determine next state
if (rxLength >= MAX_PAYLOAD_LENGTH)
@ -295,7 +301,7 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
}
// Check the lengths match
if ((rxPacketLength + rxLength + (rxObj->isSingleInstance() ? 0 : 2)) != packetSize)
if ((rxPacketLength + rxInstanceLength + rxLength) != packetSize)
{ // packet error - mismatched packet size
stats.rxErrors++;
rxState = STATE_SYNC;

View File

@ -107,6 +107,7 @@ private:
quint16 rxInstId;
quint16 rxLength;
quint16 rxPacketLength;
quint8 rxInstanceLength;
quint8 rxCSPacket, rxCS;
qint32 rxCount;

View File

@ -31,7 +31,7 @@
#include "generator_io.h"
// These special chars (regexp) will be removed from C/java identifiers
#define ENUM_SPECIAL_CHARS "[\\.\\-\\s/]"
#define ENUM_SPECIAL_CHARS "[\\.\\-\\s\\+/\\(\\)]"
void replaceCommonTags(QString& out, ObjectInfo* info);
void replaceCommonTags(QString& out);

View File

@ -50,7 +50,7 @@ bool UAVObjectGeneratorMatlab::generate(UAVObjectParser* parser,QString template
}
matlabCodeTemplate.replace( QString("$(ALLOCATIONCODE)"), matlabAllocationCode);
matlabCodeTemplate.replace( QString("$(SWITCHCODE)"), matlabSwithCode);
matlabCodeTemplate.replace( QString("$(SWITCHCODE)"), matlabSwitchCode);
matlabCodeTemplate.replace( QString("$(SAVEOBJECTSCODE)"), matlabSaveObjectsCode);
matlabCodeTemplate.replace( QString("$(FUNCTIONSCODE)"), matlabFunctionsCode);
@ -71,6 +71,7 @@ bool UAVObjectGeneratorMatlab::process_object(ObjectInfo* info)
if (info == NULL)
return false;
//Declare variables
QString objectName(info->name);
// QString objectTableName(objectName + "Objects");
QString objectTableName(objectName);
@ -80,39 +81,71 @@ bool UAVObjectGeneratorMatlab::process_object(ObjectInfo* info)
QString objectID(QString().setNum(info->id));
QString isSingleInst = boolTo01String( info->isSingleInst );
// Generate allocation code (will replace the $(ALLOCATIONCODE) tag)
matlabAllocationCode.append("\n " + tableIdxName + " = 1;\n");
matlabAllocationCode.append(" " + objectTableName + ".timestamp = 0;\n");
QString type;
QString allocfields;
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = zeros(1," + QString::number(info->fields[n]->numElements, 10) + ");\n");
else
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = 0;\n");
}
//===================================================================//
// Generate allocation code (will replace the $(ALLOCATIONCODE) tag) //
//===================================================================//
// matlabSwitchCode.append("\t\tcase " + objectID + "\n");
matlabAllocationCode.append("\n\t" + tableIdxName + " = 1;\n");
QString type;
QString allocfields;
if (0){
matlabAllocationCode.append("\t" + objectTableName + ".timestamp = 0;\n");
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
allocfields.append("\t" + objectTableName + "(1)." + info->fields[n]->name + " = zeros(1," + QString::number(info->fields[n]->numElements, 10) + ");\n");
else
allocfields.append("\t" + objectTableName + "(1)." + info->fields[n]->name + " = 0;\n");
}
}
else{
matlabAllocationCode.append("\t" + objectTableName + "=struct('timestamp', 0");
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
allocfields.append(",...\n\t\t '" + info->fields[n]->name + "', zeros(1," + QString::number(info->fields[n]->numElements, 10) + ")");
else
allocfields.append(",...\n\t\t '" + info->fields[n]->name + "', 0");
}
allocfields.append(");\n");
}
matlabAllocationCode.append(allocfields);
matlabAllocationCode.append("\t" + objectTableName.toUpper() + "_OBJID=" + objectID + ";\n");
// Generate 'swith:' code (will replace the $(SWITCHCODE) tag)
matlabSwithCode.append(" case " + objectID + "\n");
matlabSwithCode.append(" " + objectTableName + "(" + tableIdxName +") = " + functionCall + ";\n");
matlabSwithCode.append(" " + tableIdxName + " = " + tableIdxName +" + 1;\n");
// Generate objects saving code code (will replace the $(SAVEOBJECTSCODE) tag)
//=============================================================//
// Generate 'Switch:' code (will replace the $(SWITCHCODE) tag) //
//=============================================================//
matlabSwitchCode.append("\t\tcase " + objectTableName.toUpper() + "_OBJID\n");
matlabSwitchCode.append("\t\t\t" + objectTableName + "(" + tableIdxName +") = " + functionCall + ";\n");
matlabSwitchCode.append("\t\t\t" + tableIdxName + " = " + tableIdxName +" + 1;\n");
//=============================================================================//
// Generate objects saving code code (will replace the $(SAVEOBJECTSCODE) tag) //
//=============================================================================//
matlabSaveObjectsCode.append(",'"+objectTableName+"'");
// Generate functions code (will replace the $(FUNCTIONSCODE) tag)
matlabFunctionsCode.append("%%\n% " + objectName + " read function\n");
//=================================================================//
// Generate functions code (will replace the $(FUNCTIONSCODE) tag) //
//=================================================================//
//Generate function description comment
matlabFunctionsCode.append("function [" + objectName + "] = " + functionCall + "\n");
matlabFunctionsCode.append(" if " + isSingleInst + "\n");
matlabFunctionsCode.append(" headerSize = 8;\n");
matlabFunctionsCode.append(" else\n");
matlabFunctionsCode.append(" " + objectName + ".instanceID = fread(fid, 1, 'uint16');\n");
matlabFunctionsCode.append(" headerSize = 10;\n");
matlabFunctionsCode.append(" end\n\n");
matlabFunctionsCode.append(" " + objectName + ".timestamp = timestamp;\n");
matlabFunctionsCode.append("\tif " + isSingleInst + "\n");
matlabFunctionsCode.append("\t\theaderSize = 8;\n");
matlabFunctionsCode.append("\telse\n");
matlabFunctionsCode.append("\t\t" + objectName + ".instanceID = fread(fid, 1, 'uint16');\n");
matlabFunctionsCode.append("\t\theaderSize = 10;\n");
matlabFunctionsCode.append("\tend\n\n");
matlabFunctionsCode.append("\t" + objectName + ".timestamp = timestamp;\n");
// Generate functions code, actual fields of the object
QString funcfields;
@ -122,16 +155,16 @@ bool UAVObjectGeneratorMatlab::process_object(ObjectInfo* info)
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, " + QString::number(info->fields[n]->numElements, 10) + ", '" + type + "'));\n");
funcfields.append("\t" + objectName + "." + info->fields[n]->name + " = double(fread(fid, " + QString::number(info->fields[n]->numElements, 10) + ", '" + type + "'));\n");
else
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, 1, '" + type + "'));\n");
funcfields.append("\t" + objectName + "." + info->fields[n]->name + " = double(fread(fid, 1, '" + type + "'));\n");
}
matlabFunctionsCode.append(funcfields);
matlabFunctionsCode.append(" % read CRC\n");
matlabFunctionsCode.append(" fread(fid, 1, 'uint8');\n");
matlabFunctionsCode.append("\t% read CRC\n");
matlabFunctionsCode.append("\tfread(fid, 1, 'uint8');\n");
matlabFunctionsCode.append("end\n\n");
matlabFunctionsCode.append("\n\n");
return true;
}

View File

@ -37,7 +37,7 @@ public:
private:
bool process_object(ObjectInfo* info);
QString matlabAllocationCode;
QString matlabSwithCode;
QString matlabSwitchCode;
QString matlabSaveObjectsCode;
QString matlabFunctionsCode;
QStringList fieldTypeStrMatlab;

View File

@ -1,7 +1,7 @@
<xml>
<object name="ActuatorCommand" singleinstance="true" settings="false">
<description>Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule</description>
<field name="Channel" units="us" type="int16" elements="8"/>
<field name="Channel" units="us" type="int16" elements="10"/>
<field name="UpdateTime" units="ms" type="uint8" elements="1"/>
<field name="MaxUpdateTime" units="ms" type="uint16" elements="1"/>
<field name="NumFailedUpdates" units="" type="uint8" elements="1"/>

View File

@ -1,27 +1,27 @@
<xml>
<object name="ActuatorSettings" singleinstance="true" settings="true">
<description>Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType</description>
<field name="FixedWingRoll1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingRoll2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingPitch1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingPitch2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingYaw1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingYaw2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingThrottle" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorN" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorNE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorSE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorS" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorSW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="VTOLMotorNW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,None" defaultvalue="None"/>
<field name="FixedWingRoll1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingRoll2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingPitch1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingPitch2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingYaw1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingYaw2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="FixedWingThrottle" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorN" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorNE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorSE" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorS" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorSW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="VTOLMotorNW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
<field name="ChannelUpdateFreq" units="Hz" type="uint16" elements="4" defaultvalue="50"/>
<field name="ChannelMax" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelNeutral" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelMin" units="us" type="int16" elements="8" defaultvalue="1000"/>
<field name="ChannelType" units="" type="enum" elements="8" options="PWM,MK,ASTEC4,PWM Alarm Buzzer" defaultvalue="PWM"/>
<field name="ChannelAddr" units="" type="uint8" elements="8" defaultvalue="0,1,2,3,4,5,6,7"/>
<field name="ChannelMax" units="us" type="int16" elements="10" defaultvalue="1000"/>
<field name="ChannelNeutral" units="us" type="int16" elements="10" defaultvalue="1000"/>
<field name="ChannelMin" units="us" type="int16" elements="10" defaultvalue="1000"/>
<field name="ChannelType" units="" type="enum" elements="10" options="PWM,MK,ASTEC4,PWM Alarm Buzzer" defaultvalue="PWM"/>
<field name="ChannelAddr" units="" type="uint8" elements="10" defaultvalue="0,1,2,3,4,5,6,7,8,9"/>
<field name="MotorsSpinWhileArmed" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>

View File

@ -1,13 +1,13 @@
<xml>
<object name="HwSettings" singleinstance="true" settings="true">
<description>Selection of optional hardware configurations.</description>
<field name="CC_FlexiPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,Spektrum1,Spektrum2,ComAux,I2C" defaultvalue="Disabled"/>
<field name="CC_MainPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,S.Bus,GPS,Spektrum1,Spektrum2,ComAux" defaultvalue="Telemetry"/>
<field name="CC_RcvrPort" units="function" type="enum" elements="1" options="Disabled,PWM,PPM" defaultvalue="PWM"/>
<field name="CC_RcvrPort" units="function" type="enum" elements="1" options="Disabled,PWM,PPM,PPM+Servo,Servo" defaultvalue="PWM"/>
<field name="CC_MainPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,S.Bus,DSM2,DSMX (10bit),DSMX (11bit),ComAux" defaultvalue="Disabled"/>
<field name="CC_FlexiPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,I2C,DSM2,DSMX (10bit),DSMX (11bit),ComAux" defaultvalue="Disabled"/>
<field name="OP_FlexiPort" units="function" type="enum" elements="1" options="Disabled,GPS" defaultvalue="GPS"/>
<field name="OP_RcvrPort" units="function" type="enum" elements="1" options="Disabled,PWM,PPM,DSM2,DSMX (10bit),DSMX (11bit),Debug" defaultvalue="PWM"/>
<field name="OP_MainPort" units="function" type="enum" elements="1" options="Disabled,Telemetry" defaultvalue="Telemetry"/>
<field name="OP_RcvrPort" units="function" type="enum" elements="1" options="Disabled,Debug,Spektrum1,PWM,PPM" defaultvalue="PWM"/>
<field name="OP_FlexiPort" units="function" type="enum" elements="1" options="Disabled,GPS" defaultvalue="GPS"/>
<field name="TelemetrySpeed" units="bps" type="enum" elements="1" options="2400,4800,9600,19200,38400,57600,115200" defaultvalue="57600"/>
<field name="GPSSpeed" units="bps" type="enum" elements="1" options="2400,4800,9600,19200,38400,57600,115200" defaultvalue="57600"/>

View File

@ -3,7 +3,7 @@
<description>Settings to indicate how to decode receiver input by @ref ManualControlModule.</description>
<field name="ChannelGroups" units="Channel Group" type="enum"
elementnames="Throttle,Roll,Pitch,Yaw,FlightMode,Collective,Accessory0,Accessory1,Accessory2"
options="PWM,PPM,Spektrum1,Spektrum2,S.Bus,GCS,None" defaultvalue="None"/>
options="PWM,PPM,DSM (MainPort),DSM (FlexiPort),S.Bus,GCS,None" defaultvalue="None"/>
<field name="ChannelNumber" units="channel" type="uint8" defaultvalue="0"
elementnames="Throttle,Roll,Pitch,Yaw,FlightMode,Collective,Accessory0,Accessory1,Accessory2"/>
<field name="ChannelMin" units="us" type="int16" defaultvalue="1000"

View File

@ -24,6 +24,10 @@
<field name="Mixer7Vector" units="" type="int8" elements="5" elementnames="ThrottleCurve1,ThrottleCurve2,Roll,Pitch,Yaw" defaultvalue="0"/>
<field name="Mixer8Type" units="" type="enum" elements="1" options="Disabled,Motor,Servo,CameraRoll,CameraPitch,CameraYaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5" defaultvalue="Disabled"/>
<field name="Mixer8Vector" units="" type="int8" elements="5" elementnames="ThrottleCurve1,ThrottleCurve2,Roll,Pitch,Yaw" defaultvalue="0"/>
<field name="Mixer9Type" units="" type="enum" elements="1" options="Disabled,Motor,Servo,CameraRoll,CameraPitch,CameraYaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5" defaultvalue="Disabled"/>
<field name="Mixer9Vector" units="" type="int8" elements="5" elementnames="ThrottleCurve1,ThrottleCurve2,Roll,Pitch,Yaw" defaultvalue="0"/>
<field name="Mixer10Type" units="" type="enum" elements="1" options="Disabled,Motor,Servo,CameraRoll,CameraPitch,CameraYaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5" defaultvalue="Disabled"/>
<field name="Mixer10Vector" units="" type="int8" elements="5" elementnames="ThrottleCurve1,ThrottleCurve2,Roll,Pitch,Yaw" defaultvalue="0"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
<telemetryflight acked="true" updatemode="onchange" period="0"/>

View File

@ -2,7 +2,7 @@
<object name="ReceiverActivity" singleinstance="true" settings="false">
<description>Monitors which receiver channels have been active within the last second.</description>
<field name="ActiveGroup" units="Channel Group" type="enum" elements="1"
options="PWM,PPM,Spektrum1,Spektrum2,SBus,GCS,None"
options="PWM,PPM,DSM (MainPort),DSM (FlexiPort),S.Bus,GCS,None"
defaultvalue="None"/>
<field name="ActiveChannel" units="channel" type="uint8" elements="1"
defaultvalue="255"/>