From 818a42ec059f7c6a11b84db938be7dc9ced86885 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 11 Apr 2014 21:02:29 +0200 Subject: [PATCH 01/58] Fix revolution model filename casing --- .../Revolution/{Revolution.3DS => revolution.3ds} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename artwork/3D Model/boards/Revolution/{Revolution.3DS => revolution.3ds} (100%) diff --git a/artwork/3D Model/boards/Revolution/Revolution.3DS b/artwork/3D Model/boards/Revolution/revolution.3ds similarity index 100% rename from artwork/3D Model/boards/Revolution/Revolution.3DS rename to artwork/3D Model/boards/Revolution/revolution.3ds From 82c81fef6e784adab20de0860879cba6be205461 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 12 Apr 2014 22:00:02 +0200 Subject: [PATCH 02/58] OP-1302 make leds more "readable" Show alarm and arming/flightmode in sequence Alarm: Warning = rP Error = rrP Critical = R Heartbeat/flightmode: disarmed = B armed/Stabilization1 = bbP armed/Stabilization2 = bbbP armed/Stabilization3 = bbbbP armed/AH/AVario/Velocitycontrol = bvP armed/PH/Pathplanner/POI = bbvP armed/Land/RTB = bbvvP note: r/b/v = short red/blue/both blink R/B/V = long red/blue/both blink p/P = short/long pause --- flight/libraries/alarms.c | 27 ++++ flight/libraries/inc/alarms.h | 2 + flight/modules/System/systemmod.c | 256 ++++++++++++++++++++++-------- 3 files changed, 218 insertions(+), 67 deletions(-) diff --git a/flight/libraries/alarms.c b/flight/libraries/alarms.c index 0ea46c5e5..5dc3cda2e 100644 --- a/flight/libraries/alarms.c +++ b/flight/libraries/alarms.c @@ -254,6 +254,33 @@ static int32_t hasSeverity(SystemAlarmsAlarmOptions severity) xSemaphoreGiveRecursive(lock); return 0; } +/** + * Get the highest alarm severity + * @return + */ +SystemAlarmsAlarmOptions AlarmsGetHighestSeverity() +{ + SystemAlarmsAlarmData alarmsData; + SystemAlarmsAlarmOptions highest = SYSTEMALARMS_ALARM_UNINITIALISED; + + // Lock + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + + // Read alarms + SystemAlarmsAlarmGet(&alarmsData); + + // Go through alarms and find the highest severity + uint32_t n = 0; + while (n < SYSTEMALARMS_ALARM_NUMELEM && highest != SYSTEMALARMS_ALARM_CRITICAL) { + if (cast_struct_to_array(alarmsData, alarmsData.Actuator)[n] > highest) { + highest = cast_struct_to_array(alarmsData, alarmsData.Actuator)[n]; + } + n++; + } + + xSemaphoreGiveRecursive(lock); + return highest; +} /** * @} diff --git a/flight/libraries/inc/alarms.h b/flight/libraries/inc/alarms.h index 1d7a4ed3b..304916dbc 100644 --- a/flight/libraries/inc/alarms.h +++ b/flight/libraries/inc/alarms.h @@ -42,9 +42,11 @@ int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm); void AlarmsDefaultAll(); int32_t AlarmsClear(SystemAlarmsAlarmElem alarm); void AlarmsClearAll(); + int32_t AlarmsHasWarnings(); int32_t AlarmsHasErrors(); int32_t AlarmsHasCritical(); +SystemAlarmsAlarmOptions AlarmsGetHighestSeverity(); #endif // ALARMS_H diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index 648e2d3a0..d785615c8 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -72,22 +72,65 @@ #endif // Private constants -#define SYSTEM_UPDATE_PERIOD_MS 1000 -#define LED_BLINK_RATE_HZ 5 - -#ifndef IDLE_COUNTS_PER_SEC_AT_NO_LOAD -#define IDLE_COUNTS_PER_SEC_AT_NO_LOAD 995998 // calibrated by running tests/test_cpuload.c -// must be updated if the FreeRTOS or compiler -// optimisation options are changed. -#endif +#define SYSTEM_UPDATE_PERIOD_MS 500 +#define LED_BLINK_PERIOD_MS 200 #if defined(PIOS_SYSTEM_STACK_SIZE) -#define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE +#define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE #else -#define STACK_SIZE_BYTES 1024 +#define STACK_SIZE_BYTES 1024 #endif -#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#ifdef PIOS_LED_ALARM +#define ALARM_LED_ON() PIOS_LED_On(PIOS_LED_ALARM) +#define ALARM_LED_OFF() PIOS_LED_Off(PIOS_LED_ALARM) +#else +#define ALARM_LED_ON() +#define ALARM_LED_OFF() +#endif + +#ifdef PIOS_LED_HEARTBEAT +#define HEARTBEAT_LED_ON() PIOS_LED_On(PIOS_LED_HEARTBEAT) +#define HEARTBEAT_LED_OFF() PIOS_LED_Off(PIOS_LED_HEARTBEAT) +#else +#define HEARTBEAT_LED_ON() +#define HEARTBEAT_LED_OFF() +#endif + +#define ALARM_BLINK_COUNT(x) \ + (x == SYSTEMALARMS_ALARM_OK ? 0 : \ + x == SYSTEMALARMS_ALARM_WARNING ? 1 : \ + x == SYSTEMALARMS_ALARM_ERROR ? 2 : \ + x == SYSTEMALARMS_ALARM_CRITICAL ? 0 : 0) + + +#define BLINK_COUNT(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 3 : 1) + +#define BLINK_RED(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? true : false) + +#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) // Private types @@ -98,6 +141,12 @@ static enum { STACKOVERFLOW_NONE = 0, STACKOVERFLOW_WARNING = 1, STACKOVERFLOW_C static bool mallocFailed; static HwSettingsData bootHwSettings; static struct PIOS_FLASHFS_Stats fsStats; + +// led notification handling +static volatile SystemAlarmsAlarmOptions currentAlarmLevel = SYSTEMALARMS_ALARM_OK; +static volatile FlightStatusData currentFlightStatus; +static volatile bool started = false; + // Private functions static void objectUpdatedCb(UAVObjEvent *ev); static void hwSettingsUpdatedCb(UAVObjEvent *ev); @@ -170,8 +219,6 @@ MODULE_INITCALL(SystemModInitialize, 0); */ static void systemTask(__attribute__((unused)) void *parameters) { - uint8_t cycleCount = 0; - /* create all modules thread */ MODULE_TASKCREATE_ALL; @@ -189,9 +236,6 @@ static void systemTask(__attribute__((unused)) void *parameters) /* Record a successful boot */ PIOS_IAP_WriteBootCount(0); #endif - - // Initialize vars - // Listen for SettingPersistance object updates, connect a callback function ObjectPersistenceConnectQueue(objectPersistenceQueue); @@ -204,13 +248,13 @@ static void systemTask(__attribute__((unused)) void *parameters) TaskInfoData taskInfoData; CallbackInfoData callbackInfoData; #endif - + started = true; // Main system loop while (1) { + // get values to be used for led handling + FlightStatusGet((FlightStatusData *)¤tFlightStatus); + currentAlarmLevel = AlarmsGetHighestSeverity(); // Update the system statistics - - cycleCount = cycleCount > 0 ? cycleCount - 1 : 7; -// if(cycleCount == 1){ updateStats(); // Update the system alarms updateSystemAlarms(); @@ -230,35 +274,10 @@ static void systemTask(__attribute__((unused)) void *parameters) // } #endif // } - // Flash the heartbeat LED -#if defined(PIOS_LED_HEARTBEAT) - uint8_t armingStatus; - FlightStatusArmedGet(&armingStatus); - if ((armingStatus == FLIGHTSTATUS_ARMED_ARMED && (cycleCount & 0x1)) || - (armingStatus != FLIGHTSTATUS_ARMED_ARMED && (cycleCount & 0x4))) { - PIOS_LED_On(PIOS_LED_HEARTBEAT); - } else { - PIOS_LED_Off(PIOS_LED_HEARTBEAT); - } - - DEBUG_MSG("+ 0x%08x\r\n", 0xDEADBEEF); -#endif /* PIOS_LED_HEARTBEAT */ - - // Turn on the error LED if an alarm is set -#if defined(PIOS_LED_ALARM) - if (AlarmsHasCritical()) { - PIOS_LED_On(PIOS_LED_ALARM); - } else if ((AlarmsHasErrors() && (cycleCount & 0x1)) || - (!AlarmsHasErrors() && AlarmsHasWarnings() && (cycleCount & 0x4))) { - PIOS_LED_On(PIOS_LED_ALARM); - } else { - PIOS_LED_Off(PIOS_LED_ALARM); - } -#endif /* PIOS_LED_ALARM */ UAVObjEvent ev; - int delayTime = SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS / (LED_BLINK_RATE_HZ * 2); + int delayTime = SYSTEM_UPDATE_PERIOD_MS; #if defined(PIOS_INCLUDE_RFM22B) @@ -649,43 +668,146 @@ static void updateSystemAlarms() } /** - * Called by the RTOS when the CPU is idle, used to measure the CPU idle time. + * Called by the RTOS when the CPU is idle, */ void vApplicationIdleHook(void) -{} +{ + static portTickType lastRunTimestamp; + if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { + return; + } + lastRunTimestamp = xTaskGetTickCount(); + // the led will show various status information, subdivided in three phases + // - Notification + // - Alarm + // - Flight status + // they are shown using the above priority + // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end + + static enum { + STATUS_NOTIFY, + STATUS_ALARM, + STATUS_FLIGHTMODE, + STATUS_LENGHT + } status; + + static uint8_t cycleCount; + cycleCount++; + // a blink last 2 cycles. + static uint8_t blinkCount; + blinkCount = (cycleCount & 0xF) >> 1; + + if (cycleCount & 0x08) { + // add a short pause between each phase + if (cycleCount > 0xA) { + cycleCount = 0xFF; + status = (status + 1) % STATUS_LENGHT; + } + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + return; + } + + if (status == STATUS_NOTIFY) { + // Not implemented yet + status++; + } + + // Handles Alarm display + if (status == STATUS_ALARM) { +#if defined(PIOS_LED_ALARM) + if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { + if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { + // Slow blink + ALARM_LED_OFF(); + if (cycleCount & 0x4) { + ALARM_LED_OFF(); + } else { + ALARM_LED_ON(); + } + } else { + if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && + (cycleCount & 0x1)) { + ALARM_LED_ON(); + } else { + ALARM_LED_OFF(); + } + } + } else { + status++; + } +#else /* if defined(PIOS_LED_ALARM) */ + // no alarms, handle next phase + status++; + // #endif +#endif /* PIOS_LED_ALARM */ + } + + // **** Handles flightmode display + if (status == STATUS_FLIGHTMODE) { + uint8_t flightmode = currentFlightStatus.FlightMode; + + // Flash the heartbeat LED +#if defined(PIOS_LED_HEARTBEAT) + + if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { + // Slow blink + if (blinkCount < 3) { + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + } + } else { + if ((blinkCount < BLINK_COUNT(flightmode)) && + (cycleCount & 0x1)) { + // red led will be active active in last or last two (4 blinks case) blinks + if (BLINK_RED(flightmode) && + ((blinkCount == BLINK_COUNT(flightmode) - 1) || + blinkCount > 1)) { + ALARM_LED_ON(); + } + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + } + } + } +#endif /* PIOS_LED_HEARTBEAT */ + } /** * Called by the RTOS when a stack overflow is detected. */ #define DEBUG_STACK_OVERFLOW 0 -void vApplicationStackOverflowHook(__attribute__((unused)) xTaskHandle *pxTask, - __attribute__((unused)) signed portCHAR *pcTaskName) -{ - stackOverflow = STACKOVERFLOW_CRITICAL; + void vApplicationStackOverflowHook(__attribute__((unused)) xTaskHandle *pxTask, + __attribute__((unused)) signed portCHAR *pcTaskName) + { + stackOverflow = STACKOVERFLOW_CRITICAL; #if DEBUG_STACK_OVERFLOW - static volatile bool wait_here = true; - while (wait_here) { - ; - } - wait_here = true; + static volatile bool wait_here = true; + while (wait_here) { + ; + } + wait_here = true; #endif -} + } /** * Called by the RTOS when a malloc call fails. */ #define DEBUG_MALLOC_FAILURES 0 -void vApplicationMallocFailedHook(void) -{ - mallocFailed = true; + void vApplicationMallocFailedHook(void) + { + mallocFailed = true; #if DEBUG_MALLOC_FAILURES - static volatile bool wait_here = true; - while (wait_here) { - ; - } - wait_here = true; + static volatile bool wait_here = true; + while (wait_here) { + ; + } + wait_here = true; #endif -} + } /** * @} From 9ebb66fbce4a5f900e67aec4e720d6cc1a4112ed Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 12 Apr 2014 22:00:26 +0200 Subject: [PATCH 03/58] OP-1302 filter out telemetry alarms --- flight/libraries/alarms.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flight/libraries/alarms.c b/flight/libraries/alarms.c index 5dc3cda2e..7f2688a73 100644 --- a/flight/libraries/alarms.c +++ b/flight/libraries/alarms.c @@ -244,7 +244,7 @@ static int32_t hasSeverity(SystemAlarmsAlarmOptions severity) // Go through alarms and check if any are of the given severity or higher for (uint32_t n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) { - if (cast_struct_to_array(alarms, alarms.Actuator)[n] >= severity) { + if (n != SYSTEMALARMS_ALARM_TELEMETRY && cast_struct_to_array(alarms, alarms.Actuator)[n] >= severity) { xSemaphoreGiveRecursive(lock); return 1; } @@ -272,7 +272,8 @@ SystemAlarmsAlarmOptions AlarmsGetHighestSeverity() // Go through alarms and find the highest severity uint32_t n = 0; while (n < SYSTEMALARMS_ALARM_NUMELEM && highest != SYSTEMALARMS_ALARM_CRITICAL) { - if (cast_struct_to_array(alarmsData, alarmsData.Actuator)[n] > highest) { + if (n != SYSTEMALARMS_ALARM_TELEMETRY && + cast_struct_to_array(alarmsData, alarmsData.Actuator)[n] > highest) { highest = cast_struct_to_array(alarmsData, alarmsData.Actuator)[n]; } n++; From 5d637fab87a0aa72886cb8117df26c6dc4b16f91 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 13 Apr 2014 11:54:25 +0200 Subject: [PATCH 04/58] OP-1302 move stuffs away from systemmod --- flight/libraries/inc/notification.h | 37 ++++ flight/libraries/notification.c | 197 ++++++++++++++++++ flight/modules/System/systemmod.c | 168 +-------------- .../boards/revolution/firmware/Makefile | 4 + 4 files changed, 242 insertions(+), 164 deletions(-) create mode 100644 flight/libraries/inc/notification.h create mode 100644 flight/libraries/notification.c diff --git a/flight/libraries/inc/notification.h b/flight/libraries/inc/notification.h new file mode 100644 index 000000000..62a9d1c58 --- /dev/null +++ b/flight/libraries/inc/notification.h @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * + * @file notification.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief notification library + * -- + * @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 NOTIFICATION_H +#define NOTIFICATION_H + +#define LED_BLINK_PERIOD_MS 200 + +// update the status snapshot used by notifcations +void NotificationUpdateStatus(); + +// run the led notifications +void NotificationOnboardLedsRun(); + +#endif /* NOTIFICATION_H */ diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c new file mode 100644 index 000000000..f7126f08e --- /dev/null +++ b/flight/libraries/notification.c @@ -0,0 +1,197 @@ +/** + ****************************************************************************** + * + * @file notification.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief brief goes here. + * -- + * @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 + */ +#include "inc/notification.h" +#include +#include +#include +#include + +#ifdef PIOS_LED_ALARM +#define ALARM_LED_ON() PIOS_LED_On(PIOS_LED_ALARM) +#define ALARM_LED_OFF() PIOS_LED_Off(PIOS_LED_ALARM) +#else +#define ALARM_LED_ON() +#define ALARM_LED_OFF() +#endif + +#ifdef PIOS_LED_HEARTBEAT +#define HEARTBEAT_LED_ON() PIOS_LED_On(PIOS_LED_HEARTBEAT) +#define HEARTBEAT_LED_OFF() PIOS_LED_Off(PIOS_LED_HEARTBEAT) +#else +#define HEARTBEAT_LED_ON() +#define HEARTBEAT_LED_OFF() +#endif + +#define ALARM_BLINK_COUNT(x) \ + (x == SYSTEMALARMS_ALARM_OK ? 0 : \ + x == SYSTEMALARMS_ALARM_WARNING ? 1 : \ + x == SYSTEMALARMS_ALARM_ERROR ? 2 : \ + x == SYSTEMALARMS_ALARM_CRITICAL ? 0 : 0) + + +#define BLINK_COUNT(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 4 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 3 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 3 : 1) + +#define BLINK_RED(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? false : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? true : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? true : false) + +// led notification handling +static volatile SystemAlarmsAlarmOptions currentAlarmLevel = SYSTEMALARMS_ALARM_OK; +static volatile FlightStatusData currentFlightStatus; +static volatile bool started = false; + +void NotificationUpdateStatus(){ + started = true; + // get values to be used for led handling + FlightStatusGet((FlightStatusData *)¤tFlightStatus); + currentAlarmLevel = AlarmsGetHighestSeverity(); +} + +void NotificationOnboardLedsRun(){ + static portTickType lastRunTimestamp; + + if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { + return; + } + lastRunTimestamp = xTaskGetTickCount(); + // the led will show various status information, subdivided in three phases + // - Notification + // - Alarm + // - Flight status + // they are shown using the above priority + // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end + + static enum { + STATUS_NOTIFY, + STATUS_ALARM, + STATUS_FLIGHTMODE, + STATUS_LENGHT + } status; + + static uint8_t cycleCount; + cycleCount++; + // a blink last 2 cycles. + static uint8_t blinkCount; + blinkCount = (cycleCount & 0xF) >> 1; + + if (cycleCount & 0x08) { + // add a short pause between each phase + if (cycleCount > 0xA) { + cycleCount = 0xFF; + status = (status + 1) % STATUS_LENGHT; + } + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + return; + } + + if (status == STATUS_NOTIFY) { + // Not implemented yet + status++; + } + + // Handles Alarm display + if (status == STATUS_ALARM) { +#if defined(PIOS_LED_ALARM) + if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { + if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { + // Slow blink + ALARM_LED_OFF(); + if (cycleCount & 0x4) { + ALARM_LED_OFF(); + } else { + ALARM_LED_ON(); + } + } else { + if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && + (cycleCount & 0x1)) { + ALARM_LED_ON(); + } else { + ALARM_LED_OFF(); + } + } + } else { + status++; + } +#else /* if defined(PIOS_LED_ALARM) */ + // no alarms, handle next phase + status++; + // #endif +#endif /* PIOS_LED_ALARM */ + } + + // **** Handles flightmode display + if (status == STATUS_FLIGHTMODE) { + uint8_t flightmode = currentFlightStatus.FlightMode; + + // Flash the heartbeat LED +#if defined(PIOS_LED_HEARTBEAT) + + if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { + // Slow blink + if (blinkCount < 3) { + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + } + } else { + if ((blinkCount < BLINK_COUNT(flightmode)) && + (cycleCount & 0x1)) { + // red led will be active active in last or last two (4 blinks case) blinks + if (BLINK_RED(flightmode) && + ((blinkCount == BLINK_COUNT(flightmode) - 1) || + blinkCount > 1)) { + ALARM_LED_ON(); + } + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + } + } + } +#endif /* PIOS_LED_HEARTBEAT */ +} diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index d785615c8..1ad8b188e 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -42,7 +42,7 @@ #include // private includes #include "inc/systemmod.h" - +#include "notification.h" // UAVOs #include @@ -73,7 +73,6 @@ // Private constants #define SYSTEM_UPDATE_PERIOD_MS 500 -#define LED_BLINK_PERIOD_MS 200 #if defined(PIOS_SYSTEM_STACK_SIZE) #define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE @@ -81,55 +80,6 @@ #define STACK_SIZE_BYTES 1024 #endif -#ifdef PIOS_LED_ALARM -#define ALARM_LED_ON() PIOS_LED_On(PIOS_LED_ALARM) -#define ALARM_LED_OFF() PIOS_LED_Off(PIOS_LED_ALARM) -#else -#define ALARM_LED_ON() -#define ALARM_LED_OFF() -#endif - -#ifdef PIOS_LED_HEARTBEAT -#define HEARTBEAT_LED_ON() PIOS_LED_On(PIOS_LED_HEARTBEAT) -#define HEARTBEAT_LED_OFF() PIOS_LED_Off(PIOS_LED_HEARTBEAT) -#else -#define HEARTBEAT_LED_ON() -#define HEARTBEAT_LED_OFF() -#endif - -#define ALARM_BLINK_COUNT(x) \ - (x == SYSTEMALARMS_ALARM_OK ? 0 : \ - x == SYSTEMALARMS_ALARM_WARNING ? 1 : \ - x == SYSTEMALARMS_ALARM_ERROR ? 2 : \ - x == SYSTEMALARMS_ALARM_CRITICAL ? 0 : 0) - - -#define BLINK_COUNT(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 4 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 4 : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 4 : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? 3 : 1) - -#define BLINK_RED(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? true : false) - #define TASK_PRIORITY (tskIDLE_PRIORITY + 1) // Private types @@ -142,11 +92,6 @@ static bool mallocFailed; static HwSettingsData bootHwSettings; static struct PIOS_FLASHFS_Stats fsStats; -// led notification handling -static volatile SystemAlarmsAlarmOptions currentAlarmLevel = SYSTEMALARMS_ALARM_OK; -static volatile FlightStatusData currentFlightStatus; -static volatile bool started = false; - // Private functions static void objectUpdatedCb(UAVObjEvent *ev); static void hwSettingsUpdatedCb(UAVObjEvent *ev); @@ -248,12 +193,9 @@ static void systemTask(__attribute__((unused)) void *parameters) TaskInfoData taskInfoData; CallbackInfoData callbackInfoData; #endif - started = true; // Main system loop while (1) { - // get values to be used for led handling - FlightStatusGet((FlightStatusData *)¤tFlightStatus); - currentAlarmLevel = AlarmsGetHighestSeverity(); + NotificationUpdateStatus(); // Update the system statistics updateStats(); // Update the system alarms @@ -672,110 +614,8 @@ static void updateSystemAlarms() */ void vApplicationIdleHook(void) { - static portTickType lastRunTimestamp; - - if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { - return; - } - lastRunTimestamp = xTaskGetTickCount(); - // the led will show various status information, subdivided in three phases - // - Notification - // - Alarm - // - Flight status - // they are shown using the above priority - // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end - - static enum { - STATUS_NOTIFY, - STATUS_ALARM, - STATUS_FLIGHTMODE, - STATUS_LENGHT - } status; - - static uint8_t cycleCount; - cycleCount++; - // a blink last 2 cycles. - static uint8_t blinkCount; - blinkCount = (cycleCount & 0xF) >> 1; - - if (cycleCount & 0x08) { - // add a short pause between each phase - if (cycleCount > 0xA) { - cycleCount = 0xFF; - status = (status + 1) % STATUS_LENGHT; - } - HEARTBEAT_LED_OFF(); - ALARM_LED_OFF(); - return; - } - - if (status == STATUS_NOTIFY) { - // Not implemented yet - status++; - } - - // Handles Alarm display - if (status == STATUS_ALARM) { -#if defined(PIOS_LED_ALARM) - if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { - if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { - // Slow blink - ALARM_LED_OFF(); - if (cycleCount & 0x4) { - ALARM_LED_OFF(); - } else { - ALARM_LED_ON(); - } - } else { - if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && - (cycleCount & 0x1)) { - ALARM_LED_ON(); - } else { - ALARM_LED_OFF(); - } - } - } else { - status++; - } -#else /* if defined(PIOS_LED_ALARM) */ - // no alarms, handle next phase - status++; - // #endif -#endif /* PIOS_LED_ALARM */ - } - - // **** Handles flightmode display - if (status == STATUS_FLIGHTMODE) { - uint8_t flightmode = currentFlightStatus.FlightMode; - - // Flash the heartbeat LED -#if defined(PIOS_LED_HEARTBEAT) - - if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { - // Slow blink - if (blinkCount < 3) { - HEARTBEAT_LED_ON(); - } else { - HEARTBEAT_LED_OFF(); - } - } else { - if ((blinkCount < BLINK_COUNT(flightmode)) && - (cycleCount & 0x1)) { - // red led will be active active in last or last two (4 blinks case) blinks - if (BLINK_RED(flightmode) && - ((blinkCount == BLINK_COUNT(flightmode) - 1) || - blinkCount > 1)) { - ALARM_LED_ON(); - } - HEARTBEAT_LED_ON(); - } else { - HEARTBEAT_LED_OFF(); - ALARM_LED_OFF(); - } - } - } -#endif /* PIOS_LED_HEARTBEAT */ - } + NotificationOnboardLedsRun(); +} /** * Called by the RTOS when a stack overflow is detected. */ diff --git a/flight/targets/boards/revolution/firmware/Makefile b/flight/targets/boards/revolution/firmware/Makefile index 5b89372a1..93aea56d0 100644 --- a/flight/targets/boards/revolution/firmware/Makefile +++ b/flight/targets/boards/revolution/firmware/Makefile @@ -53,6 +53,8 @@ MODULES += Telemetry OPTMODULES += ComUsbBridge +SRC += $(FLIGHTLIB)/notification.c + # Include all camera options CDEFS += -DUSE_INPUT_LPF -DUSE_GIMBAL_LPF -DUSE_GIMBAL_FF @@ -96,7 +98,9 @@ endif # Optional component libraries include $(FLIGHTLIB)/rscode/library.mk + #include $(FLIGHTLIB)/PyMite/pymite.mk + include $(ROOT_DIR)/make/apps-defs.mk include $(ROOT_DIR)/make/common-defs.mk From 132aa83dff90044da7c61808be44e76dc6bdd82e Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 13 Apr 2014 12:38:07 +0200 Subject: [PATCH 05/58] OP-1302 Fix other targets --- flight/targets/boards/coptercontrol/firmware/Makefile | 4 ++++ flight/targets/boards/osd/firmware/Makefile | 2 ++ flight/targets/boards/revoproto/firmware/Makefile | 2 ++ flight/targets/boards/simposix/firmware/Makefile | 2 ++ 4 files changed, 10 insertions(+) diff --git a/flight/targets/boards/coptercontrol/firmware/Makefile b/flight/targets/boards/coptercontrol/firmware/Makefile index 6c0038305..c0cf05285 100644 --- a/flight/targets/boards/coptercontrol/firmware/Makefile +++ b/flight/targets/boards/coptercontrol/firmware/Makefile @@ -48,9 +48,13 @@ OPTMODULES += Osd/osdoutput #OPTMODULES += Altitude #OPTMODULES += Fault +SRC += $(FLIGHTLIB)/notification.c + # Include all camera options CDEFS += -DUSE_INPUT_LPF -DUSE_GIMBAL_LPF -DUSE_GIMBAL_FF + + # Erase flash firmware should be buildable from command line ifeq ($(ERASE_FLASH), YES) CDEFS += -DERASE_FLASH diff --git a/flight/targets/boards/osd/firmware/Makefile b/flight/targets/boards/osd/firmware/Makefile index 14d863b1b..3744ee56a 100644 --- a/flight/targets/boards/osd/firmware/Makefile +++ b/flight/targets/boards/osd/firmware/Makefile @@ -37,6 +37,8 @@ MODULES += Telemetry OPTMODULES = +SRC += $(FLIGHTLIB)/notification.c + # Some diagnostics CDEFS += -DDIAG_TASKS diff --git a/flight/targets/boards/revoproto/firmware/Makefile b/flight/targets/boards/revoproto/firmware/Makefile index 2e5df1ac3..16e4d7072 100644 --- a/flight/targets/boards/revoproto/firmware/Makefile +++ b/flight/targets/boards/revoproto/firmware/Makefile @@ -50,6 +50,8 @@ MODULES += Osd/osdoutout MODULES += Logging MODULES += Telemetry +SRC += $(FLIGHTLIB)/notification.c + OPTMODULES += ComUsbBridge # Include all camera options diff --git a/flight/targets/boards/simposix/firmware/Makefile b/flight/targets/boards/simposix/firmware/Makefile index beda566a8..d6c1f0a14 100644 --- a/flight/targets/boards/simposix/firmware/Makefile +++ b/flight/targets/boards/simposix/firmware/Makefile @@ -45,6 +45,8 @@ MODULES += Airspeed MODULES += AltitudeHold #MODULES += OveroSync +SRC += $(FLIGHTLIB)/notification.c + # Paths OPSYSTEM = . BOARDINC = .. From 299f388245d25d5d72593809028a6717c3488701 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 13 Apr 2014 17:42:57 +0200 Subject: [PATCH 06/58] OP-1302 Add a stub pios_notify API for user interaction/notifications right now all notifications produces the same output, the DRAW_ATTENTION sequence --- flight/libraries/inc/notification.h | 29 ++- flight/libraries/notification.c | 233 +++++++++++------- flight/modules/System/systemmod.c | 42 ++-- flight/pios/common/pios_notify.c | 49 ++++ flight/pios/inc/pios_notify.h | 58 +++++ .../targets/boards/simposix/firmware/Makefile | 2 + make/apps-defs.mk | 2 +- 7 files changed, 295 insertions(+), 120 deletions(-) create mode 100644 flight/pios/common/pios_notify.c create mode 100644 flight/pios/inc/pios_notify.h diff --git a/flight/libraries/inc/notification.h b/flight/libraries/inc/notification.h index 62a9d1c58..65b902d1d 100644 --- a/flight/libraries/inc/notification.h +++ b/flight/libraries/inc/notification.h @@ -1,32 +1,35 @@ /** ****************************************************************************** * - * @file notification.h + * @file notification.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. * @brief notification library * -- * @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 +/* + * 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 + * + * 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., + * + * 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 NOTIFICATION_H #define NOTIFICATION_H -#define LED_BLINK_PERIOD_MS 200 +// period of each blink phase +#define LED_BLINK_PERIOD_MS 200 +// Define the pause in half blink periods to be added between phases +#define LED_PAUSE_BETWEEN_PHASES 3 // update the status snapshot used by notifcations void NotificationUpdateStatus(); diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c index f7126f08e..a7f722bc2 100644 --- a/flight/libraries/notification.c +++ b/flight/libraries/notification.c @@ -1,26 +1,26 @@ /** ****************************************************************************** * - * @file notification.c + * @file notification.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. - * @brief brief goes here. + * @brief notification library. * -- * @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 +/* + * 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 + * + * 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., + * + * 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 */ #include "inc/notification.h" @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef PIOS_LED_ALARM #define ALARM_LED_ON() PIOS_LED_On(PIOS_LED_ALARM) @@ -53,9 +54,9 @@ #define BLINK_COUNT(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 4 : \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 1 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 2 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 3 : \ x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 2 : \ x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 2 : \ x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 2 : \ @@ -82,27 +83,31 @@ static volatile SystemAlarmsAlarmOptions currentAlarmLevel = SYSTEMALARMS_ALARM_OK; static volatile FlightStatusData currentFlightStatus; static volatile bool started = false; +static volatile pios_notify_notification nextNotification = NOTIFY_NONE; -void NotificationUpdateStatus(){ +#ifdef PIOS_LED_ALARM +static bool handleAlarms(uint8_t cycleCount, uint8_t blinkCount); +#endif // PIOS_LED_ALARM +static bool handleNotifications(uint8_t cycleCount, pios_notify_notification runningNotification); +static void handleStatus(uint8_t cycleCount, uint8_t blinkCount); + +void NotificationUpdateStatus() +{ started = true; // get values to be used for led handling FlightStatusGet((FlightStatusData *)¤tFlightStatus); currentAlarmLevel = AlarmsGetHighestSeverity(); + if (nextNotification == NOTIFY_NONE) { + nextNotification = PIOS_NOTIFY_GetActiveNotification(true); + } } -void NotificationOnboardLedsRun(){ +void NotificationOnboardLedsRun() +{ static portTickType lastRunTimestamp; - - if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { - return; - } - lastRunTimestamp = xTaskGetTickCount(); - // the led will show various status information, subdivided in three phases - // - Notification - // - Alarm - // - Flight status - // they are shown using the above priority - // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end + static uint8_t blinkCount; // number of blinks since phase start + static uint8_t cycleCount; // cound the number of cycles (half of a blink) + static pios_notify_notification runningNotification = NOTIFY_NONE; static enum { STATUS_NOTIFY, @@ -111,87 +116,145 @@ void NotificationOnboardLedsRun(){ STATUS_LENGHT } status; - static uint8_t cycleCount; - cycleCount++; - // a blink last 2 cycles. - static uint8_t blinkCount; - blinkCount = (cycleCount & 0xF) >> 1; - if (cycleCount & 0x08) { - // add a short pause between each phase - if (cycleCount > 0xA) { - cycleCount = 0xFF; - status = (status + 1) % STATUS_LENGHT; - } - HEARTBEAT_LED_OFF(); - ALARM_LED_OFF(); + if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { return; } + lastRunTimestamp = xTaskGetTickCount(); + + // the led will show various status information, subdivided in three phases + // - Notification + // - Alarm + // - Flight status + // they are shown using the above priority + // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end + + cycleCount++; + + // Notifications are "modal" to other statuses so they takes precedence + if (status != STATUS_NOTIFY && nextNotification != NOTIFY_NONE) { + // Force a notification status + runningNotification = nextNotification; + nextNotification = NOTIFY_NONE; + + status = STATUS_NOTIFY; + cycleCount = 0; // instantly start a notify cycle + } + + // check if a phase has just finished + if (cycleCount & 0x08) { + // add a short pause between each phase + if (cycleCount > 0x8 + LED_PAUSE_BETWEEN_PHASES) { + // ready to start a new phase + cycleCount = 0x0; + + // Notification has been already shown, so clear the running one + if (status == STATUS_NOTIFY) { + runningNotification = NOTIFY_NONE; + } + status = (status + 1) % STATUS_LENGHT; + } else { + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + return; + } + } + + // a blink last 2 cycles. + blinkCount = (cycleCount & 0xF) >> 1; + if (status == STATUS_NOTIFY) { - // Not implemented yet - status++; + if (!handleNotifications(cycleCount, runningNotification)) { + status++; + } } // Handles Alarm display if (status == STATUS_ALARM) { -#if defined(PIOS_LED_ALARM) - if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { - if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { - // Slow blink - ALARM_LED_OFF(); - if (cycleCount & 0x4) { - ALARM_LED_OFF(); - } else { - ALARM_LED_ON(); - } - } else { - if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && - (cycleCount & 0x1)) { - ALARM_LED_ON(); - } else { - ALARM_LED_OFF(); - } - } - } else { +#ifdef PIOS_LED_ALARM + if (!handleAlarms(cycleCount, blinkCount)) { status++; } -#else /* if defined(PIOS_LED_ALARM) */ - // no alarms, handle next phase +#else status++; - // #endif -#endif /* PIOS_LED_ALARM */ +#endif // PIOS_LED_ALARM } - // **** Handles flightmode display if (status == STATUS_FLIGHTMODE) { - uint8_t flightmode = currentFlightStatus.FlightMode; + handleStatus(cycleCount, blinkCount); + } +} - // Flash the heartbeat LED -#if defined(PIOS_LED_HEARTBEAT) - - if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { +#if defined(PIOS_LED_ALARM) +static bool handleAlarms(uint8_t cycleCount, uint8_t blinkCount) +{ + if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { + if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { // Slow blink - if (blinkCount < 3) { - HEARTBEAT_LED_ON(); + ALARM_LED_OFF(); + if (cycleCount & 0x4) { + ALARM_LED_OFF(); } else { - HEARTBEAT_LED_OFF(); + ALARM_LED_ON(); } } else { - if ((blinkCount < BLINK_COUNT(flightmode)) && + if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && (cycleCount & 0x1)) { - // red led will be active active in last or last two (4 blinks case) blinks - if (BLINK_RED(flightmode) && - ((blinkCount == BLINK_COUNT(flightmode) - 1) || - blinkCount > 1)) { - ALARM_LED_ON(); - } - HEARTBEAT_LED_ON(); + ALARM_LED_ON(); } else { - HEARTBEAT_LED_OFF(); ALARM_LED_OFF(); } } + return true; + } else { + return false; + } +} +#endif /* PIOS_LED_ALARM */ + + +static bool handleNotifications(uint8_t cycleCount, pios_notify_notification runningNotification) +{ + if (runningNotification == NOTIFY_NONE) { + return false; + } + if (cycleCount & 0x1) { + ALARM_LED_OFF(); + HEARTBEAT_LED_ON(); + } else { + ALARM_LED_ON(); + HEARTBEAT_LED_OFF(); + } + return true; +} + +static void handleStatus(uint8_t cycleCount, uint8_t blinkCount) +{ + // Flash the heartbeat LED +#if defined(PIOS_LED_HEARTBEAT) + uint8_t flightmode = currentFlightStatus.FlightMode; + if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { + // Slow blink + if (blinkCount < 3) { + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + } + } else { + if ((blinkCount < BLINK_COUNT(flightmode)) && + (cycleCount & 0x1)) { + // red led will be active active in last or last two (4 blinks case) blinks + if (BLINK_RED(flightmode) && + ((blinkCount == BLINK_COUNT(flightmode) - 1) || + blinkCount > 1)) { + ALARM_LED_ON(); + } + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + } } #endif /* PIOS_LED_HEARTBEAT */ } diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index 1ad8b188e..c61a3bbc6 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -72,7 +72,7 @@ #endif // Private constants -#define SYSTEM_UPDATE_PERIOD_MS 500 +#define SYSTEM_UPDATE_PERIOD_MS 250 #if defined(PIOS_SYSTEM_STACK_SIZE) #define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE @@ -80,7 +80,7 @@ #define STACK_SIZE_BYTES 1024 #endif -#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) // Private types @@ -620,34 +620,34 @@ void vApplicationIdleHook(void) * Called by the RTOS when a stack overflow is detected. */ #define DEBUG_STACK_OVERFLOW 0 - void vApplicationStackOverflowHook(__attribute__((unused)) xTaskHandle *pxTask, - __attribute__((unused)) signed portCHAR *pcTaskName) - { - stackOverflow = STACKOVERFLOW_CRITICAL; +void vApplicationStackOverflowHook(__attribute__((unused)) xTaskHandle *pxTask, + __attribute__((unused)) signed portCHAR *pcTaskName) +{ + stackOverflow = STACKOVERFLOW_CRITICAL; #if DEBUG_STACK_OVERFLOW - static volatile bool wait_here = true; - while (wait_here) { - ; - } - wait_here = true; -#endif + static volatile bool wait_here = true; + while (wait_here) { + ; } + wait_here = true; +#endif +} /** * Called by the RTOS when a malloc call fails. */ #define DEBUG_MALLOC_FAILURES 0 - void vApplicationMallocFailedHook(void) - { - mallocFailed = true; +void vApplicationMallocFailedHook(void) +{ + mallocFailed = true; #if DEBUG_MALLOC_FAILURES - static volatile bool wait_here = true; - while (wait_here) { - ; - } - wait_here = true; -#endif + static volatile bool wait_here = true; + while (wait_here) { + ; } + wait_here = true; +#endif +} /** * @} diff --git a/flight/pios/common/pios_notify.c b/flight/pios/common/pios_notify.c new file mode 100644 index 000000000..bf83c22eb --- /dev/null +++ b/flight/pios/common/pios_notify.c @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * + * @file pios_notify.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief Handles user notifications. + * -- + * @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 + */ + +#include "pios_notify.h" + +static volatile pios_notify_notification currentNotification = NOTIFY_NONE; +static volatile pios_notify_priority currentPriority; + + +void PIOS_NOTIFY_StartNotification(pios_notify_notification notification, pios_notify_priority priority) +{ + if (currentNotification == NOTIFY_NONE || currentPriority < priority) { + currentPriority = priority; + currentNotification = notification; + } +} + +pios_notify_notification PIOS_NOTIFY_GetActiveNotification(bool clear) +{ + pios_notify_notification ret = currentNotification; + + if (clear && ret != NOTIFY_NONE) { + currentNotification = NOTIFY_NONE; + } + return ret; +} diff --git a/flight/pios/inc/pios_notify.h b/flight/pios/inc/pios_notify.h new file mode 100644 index 000000000..1e800df5c --- /dev/null +++ b/flight/pios/inc/pios_notify.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * + * @file pios_notify.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief Handles user notifications. + * -- + * @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_NOTIFY_H_ +#define PIOS_NOTIFY_H_ +#include + +typedef enum { + NOTIFY_NONE = 0, + NOTIFY_OK, + NOTIFY_NOK, + NOTIFY_DRAW_ATTENTION +} pios_notify_notification; + +typedef enum { + NOTIFY_PRIORITY_CRITICAL = 2, + NOTIFY_PRIORITY_REGULAR = 1, + NOTIFY_PRIORITY_LOW = 0, +} pios_notify_priority; + +/** + * start a new notification. If a notification is active it will be overwritten if its priority is lower than the new one. + * The new will be discarded otherwise + * @param notification kind of notification + * @param priority priority of the new notification + */ +void PIOS_NOTIFY_StartNotification(pios_notify_notification notification, pios_notify_priority priority); + +/** + * retrieve any active notification + * @param clear + * @return + */ +pios_notify_notification PIOS_NOTIFY_GetActiveNotification(bool clear); + +#endif /* PIOS_NOTIFY_H_ */ diff --git a/flight/targets/boards/simposix/firmware/Makefile b/flight/targets/boards/simposix/firmware/Makefile index d6c1f0a14..5169ef268 100644 --- a/flight/targets/boards/simposix/firmware/Makefile +++ b/flight/targets/boards/simposix/firmware/Makefile @@ -104,6 +104,8 @@ SRC += $(PIOSCORECOMMON)/pios_dosfs_logfs.c SRC += $(PIOSCORECOMMON)/pios_debuglog.c SRC += $(PIOSCORECOMMON)/pios_callbackscheduler.c SRC += $(PIOSCORECOMMON)/pios_deltatime.c +SRC += $(PIOSCORECOMMON)/pios_notify.c + ## PIOS Hardware include $(PIOS)/posix/library.mk diff --git a/make/apps-defs.mk b/make/apps-defs.mk index 20853c568..88dfe4121 100644 --- a/make/apps-defs.mk +++ b/make/apps-defs.mk @@ -99,7 +99,7 @@ SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS system code SRC += $(PIOSCOMMON)/pios_task_monitor.c SRC += $(PIOSCOMMON)/pios_callbackscheduler.c - +SRC += $(PIOSCOMMON)/pios_notify.c ## Misc library functions SRC += $(FLIGHTLIB)/fifo_buffer.c SRC += $(FLIGHTLIB)/sanitycheck.c From 20508314f25f96c296bc6998da443dd148a15c6b Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 13 Apr 2014 17:56:20 +0200 Subject: [PATCH 07/58] OP-1302 use pios_notify api to alert user of ongoing CF gyro calibration --- flight/libraries/notification.c | 57 ++++++++++++----------- flight/modules/Attitude/attitude.c | 4 +- flight/modules/StateEstimation/filtercf.c | 4 +- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c index a7f722bc2..1b5a9c752 100644 --- a/flight/libraries/notification.c +++ b/flight/libraries/notification.c @@ -116,13 +116,11 @@ void NotificationOnboardLedsRun() STATUS_LENGHT } status; - if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { return; } lastRunTimestamp = xTaskGetTickCount(); - // the led will show various status information, subdivided in three phases // - Notification // - Alarm @@ -131,25 +129,24 @@ void NotificationOnboardLedsRun() // a phase last exactly 8 cycles (so bit 1<<4 is used to determine if a phase end cycleCount++; - // Notifications are "modal" to other statuses so they takes precedence if (status != STATUS_NOTIFY && nextNotification != NOTIFY_NONE) { - // Force a notification status + // read next notification to show runningNotification = nextNotification; nextNotification = NOTIFY_NONE; - + // Force a notification status status = STATUS_NOTIFY; cycleCount = 0; // instantly start a notify cycle } // check if a phase has just finished if (cycleCount & 0x08) { - // add a short pause between each phase + // add a pause between each phase if (cycleCount > 0x8 + LED_PAUSE_BETWEEN_PHASES) { // ready to start a new phase cycleCount = 0x0; - // Notification has been already shown, so clear the running one + // Notification has been just shown, cleanup if (status == STATUS_NOTIFY) { runningNotification = NOTIFY_NONE; } @@ -161,11 +158,12 @@ void NotificationOnboardLedsRun() } } - // a blink last 2 cycles. + // a blink last 2 cycles(on and off cycle). blinkCount = (cycleCount & 0xF) >> 1; if (status == STATUS_NOTIFY) { if (!handleNotifications(cycleCount, runningNotification)) { + // no notifications, advance status++; } } @@ -174,12 +172,15 @@ void NotificationOnboardLedsRun() if (status == STATUS_ALARM) { #ifdef PIOS_LED_ALARM if (!handleAlarms(cycleCount, blinkCount)) { + // no alarms, advance status++; } #else + // no alarms leds, advance status++; #endif // PIOS_LED_ALARM } + // **** Handles flightmode display if (status == STATUS_FLIGHTMODE) { handleStatus(cycleCount, blinkCount); @@ -189,27 +190,27 @@ void NotificationOnboardLedsRun() #if defined(PIOS_LED_ALARM) static bool handleAlarms(uint8_t cycleCount, uint8_t blinkCount) { - if (currentAlarmLevel > SYSTEMALARMS_ALARM_OK) { - if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { - // Slow blink - ALARM_LED_OFF(); - if (cycleCount & 0x4) { - ALARM_LED_OFF(); - } else { - ALARM_LED_ON(); - } - } else { - if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && - (cycleCount & 0x1)) { - ALARM_LED_ON(); - } else { - ALARM_LED_OFF(); - } - } - return true; - } else { + if (currentAlarmLevel == SYSTEMALARMS_ALARM_OK) { return false; } + + if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { + // Slow blink + ALARM_LED_OFF(); + if (cycleCount & 0x4) { + ALARM_LED_OFF(); + } else { + ALARM_LED_ON(); + } + } else { + if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && + (cycleCount & 0x1)) { + ALARM_LED_ON(); + } else { + ALARM_LED_OFF(); + } + } + return true; } #endif /* PIOS_LED_ALARM */ @@ -244,7 +245,7 @@ static void handleStatus(uint8_t cycleCount, uint8_t blinkCount) } else { if ((blinkCount < BLINK_COUNT(flightmode)) && (cycleCount & 0x1)) { - // red led will be active active in last or last two (4 blinks case) blinks + // red led will be active active on last (1-3 blinks) or last two (4 blinks case) blinks if (BLINK_RED(flightmode) && ((blinkCount == BLINK_COUNT(flightmode) - 1) || blinkCount > 1)) { diff --git a/flight/modules/Attitude/attitude.c b/flight/modules/Attitude/attitude.c index e004c04b3..92f07ae01 100644 --- a/flight/modules/Attitude/attitude.c +++ b/flight/modules/Attitude/attitude.c @@ -63,7 +63,7 @@ #include "taskinfo.h" #include "CoordinateConversions.h" - +#include // Private constants #define STACK_SIZE_BYTES 540 @@ -252,6 +252,7 @@ static void AttitudeTask(__attribute__((unused)) void *parameters) rollPitchBiasRate = 0.01f; accel_filter_enabled = false; init = 0; + PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR); } else if (zero_during_arming && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { accelKp = 1.0f; accelKi = 0.0f; @@ -259,6 +260,7 @@ static void AttitudeTask(__attribute__((unused)) void *parameters) rollPitchBiasRate = 0.01f; accel_filter_enabled = false; init = 0; + PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR); } else if (init == 0) { // Reload settings (all the rates) AttitudeSettingsAccelKiGet(&accelKi); diff --git a/flight/modules/StateEstimation/filtercf.c b/flight/modules/StateEstimation/filtercf.c index 992eef8ef..0daea0928 100644 --- a/flight/modules/StateEstimation/filtercf.c +++ b/flight/modules/StateEstimation/filtercf.c @@ -42,7 +42,7 @@ #include #include - +#include // Private constants #define STACK_REQUIRED 512 @@ -295,6 +295,7 @@ static int32_t complementaryFilter(struct data *this, float gyro[3], float accel this->accel_filter_enabled = false; this->rollPitchBiasRate = 0.01f; this->attitudeSettings.MagKp = this->magCalibrated ? 1.0f : 0.0f; + PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR); } else if ((this->attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { this->attitudeSettings.AccelKp = 1.0f; this->attitudeSettings.AccelKi = 0.0f; @@ -303,6 +304,7 @@ static int32_t complementaryFilter(struct data *this, float gyro[3], float accel this->rollPitchBiasRate = 0.01f; this->attitudeSettings.MagKp = this->magCalibrated ? 1.0f : 0.0f; this->init = 0; + PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR); } else if (this->init == 0) { // Reload settings (all the rates) AttitudeSettingsGet(&this->attitudeSettings); From ee91207ede61b56715df0dc0434fcb6561fe73b0 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 16 Apr 2014 07:57:15 +0200 Subject: [PATCH 08/58] OP-1302 simplify the code adding some pattern "tables" --- flight/libraries/inc/notification.h | 4 +- flight/libraries/notification.c | 219 +++++++++++++++------------- 2 files changed, 117 insertions(+), 106 deletions(-) diff --git a/flight/libraries/inc/notification.h b/flight/libraries/inc/notification.h index 65b902d1d..2053a9609 100644 --- a/flight/libraries/inc/notification.h +++ b/flight/libraries/inc/notification.h @@ -27,9 +27,7 @@ #define NOTIFICATION_H // period of each blink phase -#define LED_BLINK_PERIOD_MS 200 -// Define the pause in half blink periods to be added between phases -#define LED_PAUSE_BETWEEN_PHASES 3 +#define LED_BLINK_PERIOD_MS 200 // update the status snapshot used by notifcations void NotificationUpdateStatus(); diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c index 1b5a9c752..4df6f71bb 100644 --- a/flight/libraries/notification.c +++ b/flight/libraries/notification.c @@ -46,38 +46,82 @@ #define HEARTBEAT_LED_OFF() #endif -#define ALARM_BLINK_COUNT(x) \ +#define BLINK_R_ALARM_PATTERN(x) \ (x == SYSTEMALARMS_ALARM_OK ? 0 : \ - x == SYSTEMALARMS_ALARM_WARNING ? 1 : \ - x == SYSTEMALARMS_ALARM_ERROR ? 2 : \ + x == SYSTEMALARMS_ALARM_WARNING ? 0b0000000001000000 : \ + x == SYSTEMALARMS_ALARM_ERROR ? 0b0000001000100000 : \ + x == SYSTEMALARMS_ALARM_CRITICAL ? 0b0111111111111110 : 0) +#define BLINK_B_ALARM_PATTERN(x) \ + (x == SYSTEMALARMS_ALARM_OK ? 0 : \ + x == SYSTEMALARMS_ALARM_WARNING ? 0 : \ + x == SYSTEMALARMS_ALARM_ERROR ? 0 : \ x == SYSTEMALARMS_ALARM_CRITICAL ? 0 : 0) -#define BLINK_COUNT(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 1 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 2 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 4 : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 4 : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 3 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? 3 : 1) +#define BLINK_B_FM_ARMED_PATTERN(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000010000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000010000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001000100010001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001000100010001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0000010000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0000010000100001 : 0b0000000000000001) -#define BLINK_RED(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? false : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? true : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? true : false) +#define BLINK_R_FM_ARMED_PATTERN(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0000000000100000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0000000000100000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0000000000100000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000010000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001000100000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001000100000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0000010000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0000010000000000 : 0b0000010000000000) + +#define BLINK_B_FM_DISARMED_PATTERN(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0001111111111111 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0001111111111111 : 0b0001111111111111) + +#define BLINK_R_FM_DISARMED_PATTERN(x) \ + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0 : 0) + + +#define BLINK_B_NOTIFY_PATTERN(x) \ + (x == NOTIFY_NONE ? 0 : \ + x == NOTIFY_OK ? 0b0000100100111111 : \ + x == NOTIFY_NOK ? 0b0000000000111111 : \ + x == NOTIFY_DRAW_ATTENTION ? 0b0101010101010101 : 0b0101010101010101) + +#define BLINK_R_NOTIFY_PATTERN(x) \ + (x == NOTIFY_NONE ? 0 : \ + x == NOTIFY_OK ? 0b0000000000001111 : \ + x == NOTIFY_NOK ? 0b0011000011001111 : \ + x == NOTIFY_DRAW_ATTENTION ? 0b1010101010101010 : 0b1010101010101010) // led notification handling static volatile SystemAlarmsAlarmOptions currentAlarmLevel = SYSTEMALARMS_ALARM_OK; @@ -86,10 +130,10 @@ static volatile bool started = false; static volatile pios_notify_notification nextNotification = NOTIFY_NONE; #ifdef PIOS_LED_ALARM -static bool handleAlarms(uint8_t cycleCount, uint8_t blinkCount); +static bool handleAlarms(uint16_t *r_pattern, uint16_t *b_pattern); #endif // PIOS_LED_ALARM -static bool handleNotifications(uint8_t cycleCount, pios_notify_notification runningNotification); -static void handleStatus(uint8_t cycleCount, uint8_t blinkCount); +static bool handleNotifications(pios_notify_notification runningNotification, uint16_t *r_pattern, uint16_t *b_pattern); +static void handleStatus(uint16_t *r_pattern, uint16_t *b_pattern); void NotificationUpdateStatus() { @@ -105,8 +149,9 @@ void NotificationUpdateStatus() void NotificationOnboardLedsRun() { static portTickType lastRunTimestamp; - static uint8_t blinkCount; // number of blinks since phase start - static uint8_t cycleCount; // cound the number of cycles (half of a blink) + static uint16_t r_pattern; + static uint16_t b_pattern; + static uint8_t cycleCount; // count the number of cycles static pios_notify_notification runningNotification = NOTIFY_NONE; static enum { @@ -116,7 +161,7 @@ void NotificationOnboardLedsRun() STATUS_LENGHT } status; - if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 2)) { + if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 4)) { return; } @@ -140,29 +185,19 @@ void NotificationOnboardLedsRun() } // check if a phase has just finished - if (cycleCount & 0x08) { - // add a pause between each phase - if (cycleCount > 0x8 + LED_PAUSE_BETWEEN_PHASES) { - // ready to start a new phase - cycleCount = 0x0; - - // Notification has been just shown, cleanup - if (status == STATUS_NOTIFY) { - runningNotification = NOTIFY_NONE; - } - status = (status + 1) % STATUS_LENGHT; - } else { - HEARTBEAT_LED_OFF(); - ALARM_LED_OFF(); - return; + if (cycleCount & 0x10) { + HEARTBEAT_LED_OFF(); + ALARM_LED_OFF(); + cycleCount = 0x0; + // Notification has been just shown, cleanup + if (status == STATUS_NOTIFY) { + runningNotification = NOTIFY_NONE; } + status = (status + 1) % STATUS_LENGHT; } - // a blink last 2 cycles(on and off cycle). - blinkCount = (cycleCount & 0xF) >> 1; - if (status == STATUS_NOTIFY) { - if (!handleNotifications(cycleCount, runningNotification)) { + if (!cycleCount && !handleNotifications(runningNotification, &r_pattern, &b_pattern)) { // no notifications, advance status++; } @@ -171,7 +206,7 @@ void NotificationOnboardLedsRun() // Handles Alarm display if (status == STATUS_ALARM) { #ifdef PIOS_LED_ALARM - if (!handleAlarms(cycleCount, blinkCount)) { + if (!cycleCount && !handleAlarms(&r_pattern, &b_pattern)) { // no alarms, advance status++; } @@ -182,80 +217,58 @@ void NotificationOnboardLedsRun() } // **** Handles flightmode display - if (status == STATUS_FLIGHTMODE) { - handleStatus(cycleCount, blinkCount); + if (status == STATUS_FLIGHTMODE && !cycleCount) { + handleStatus(&r_pattern, &b_pattern); } + + // led output + if (b_pattern & 0x1) { + HEARTBEAT_LED_ON(); + } else { + HEARTBEAT_LED_OFF(); + } + if (r_pattern & 0x1) { + ALARM_LED_ON(); + } else { + ALARM_LED_OFF(); + } + r_pattern >>= 1; + b_pattern >>= 1; } #if defined(PIOS_LED_ALARM) -static bool handleAlarms(uint8_t cycleCount, uint8_t blinkCount) +static bool handleAlarms(uint16_t *r_pattern, uint16_t *b_pattern) { if (currentAlarmLevel == SYSTEMALARMS_ALARM_OK) { return false; } - - if (currentAlarmLevel == SYSTEMALARMS_ALARM_CRITICAL) { - // Slow blink - ALARM_LED_OFF(); - if (cycleCount & 0x4) { - ALARM_LED_OFF(); - } else { - ALARM_LED_ON(); - } - } else { - if ((blinkCount < (ALARM_BLINK_COUNT(currentAlarmLevel))) && - (cycleCount & 0x1)) { - ALARM_LED_ON(); - } else { - ALARM_LED_OFF(); - } - } + *b_pattern = BLINK_B_ALARM_PATTERN(currentAlarmLevel); + *r_pattern = BLINK_R_ALARM_PATTERN(currentAlarmLevel); return true; } #endif /* PIOS_LED_ALARM */ -static bool handleNotifications(uint8_t cycleCount, pios_notify_notification runningNotification) +static bool handleNotifications(pios_notify_notification runningNotification, uint16_t *r_pattern, uint16_t *b_pattern) { if (runningNotification == NOTIFY_NONE) { return false; } - if (cycleCount & 0x1) { - ALARM_LED_OFF(); - HEARTBEAT_LED_ON(); - } else { - ALARM_LED_ON(); - HEARTBEAT_LED_OFF(); - } + *b_pattern = BLINK_B_NOTIFY_PATTERN(runningNotification); + *r_pattern = BLINK_R_NOTIFY_PATTERN(runningNotification); return true; } -static void handleStatus(uint8_t cycleCount, uint8_t blinkCount) +static void handleStatus(uint16_t *r_pattern, uint16_t *b_pattern) { // Flash the heartbeat LED -#if defined(PIOS_LED_HEARTBEAT) uint8_t flightmode = currentFlightStatus.FlightMode; + if (currentFlightStatus.Armed == FLIGHTSTATUS_ARMED_DISARMED) { - // Slow blink - if (blinkCount < 3) { - HEARTBEAT_LED_ON(); - } else { - HEARTBEAT_LED_OFF(); - } + *b_pattern = BLINK_B_FM_DISARMED_PATTERN(flightmode); + *r_pattern = BLINK_R_FM_DISARMED_PATTERN(flightmode); } else { - if ((blinkCount < BLINK_COUNT(flightmode)) && - (cycleCount & 0x1)) { - // red led will be active active on last (1-3 blinks) or last two (4 blinks case) blinks - if (BLINK_RED(flightmode) && - ((blinkCount == BLINK_COUNT(flightmode) - 1) || - blinkCount > 1)) { - ALARM_LED_ON(); - } - HEARTBEAT_LED_ON(); - } else { - HEARTBEAT_LED_OFF(); - ALARM_LED_OFF(); - } + *b_pattern = BLINK_B_FM_ARMED_PATTERN(flightmode); + *r_pattern = BLINK_R_FM_ARMED_PATTERN(flightmode); } -#endif /* PIOS_LED_HEARTBEAT */ } From 46f70a74c8df9805452e808ea4e69e71ff36770c Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 16:57:16 +0200 Subject: [PATCH 09/58] OP-1312 Initial version running on DiscoveryF4 --- flight/pios/inc/pios_ws2811.h | 87 ++++++ flight/pios/stm32f4xx/pios_ws2811.c | 248 ++++++++++++++++++ .../boards/discoveryf4bare/board_hw_defs.c | 112 ++++++++ .../discoveryf4bare/firmware/pios_board.c | 3 +- 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 flight/pios/inc/pios_ws2811.h create mode 100644 flight/pios/stm32f4xx/pios_ws2811.c diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h new file mode 100644 index 000000000..0e660bdb0 --- /dev/null +++ b/flight/pios/inc/pios_ws2811.h @@ -0,0 +1,87 @@ +/** + ****************************************************************************** + * + * @file pios_ws2811.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief A driver for ws2811 rgb led controller. + * this is a plain PiOS port of the very clever solution + * implemented by Omri Iluz in the chibios driver here: + * https://github.com/omriiluz/WS2812B-LED-Driver-ChibiOS + * @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_WS2811_H_ +#define PIOS_WS2811_H_ + +#include +#include +#include +#include +#include +#include +#include + + +#define sign(x) ((x > 0) - (x < 0)) +#define PIOS_WS2811_NUMLEDS 2 +#define PIOS_WS2811_BUFFER_SIZE (((PIOS_WS2811_NUMLEDS) * 24)) +#define PIOS_WS2811_MEMORYDATASIZE DMA_MemoryDataSize_HalfWord +#define PIOS_WS2811_PERIPHERALDATASIZE DMA_PeripheralDataSize_HalfWord +#define PIOS_WS2811_TIM_PERIOD 20 + +typedef uint16_t ledbuf_t; + +typedef struct Color Color; +struct Color { + uint8_t R; + uint8_t G; + uint8_t B; +}; +struct pios_ws2811_pin_cfg{ + GPIO_TypeDef *gpio; + GPIO_InitTypeDef gpioInit; +}; +struct pios_ws2811_cfg { + TIM_TimeBaseInitTypeDef timerInit; + TIM_TypeDef *timer; + uint8_t timerCh1; + uint8_t timerCh2; + + DMA_InitTypeDef dmaInitCh1; + DMA_Stream_TypeDef *streamCh1; + uint32_t dmaItCh1; + + DMA_InitTypeDef dmaInitCh2; + DMA_Stream_TypeDef *streamCh2; + uint32_t dmaItCh2; + + DMA_InitTypeDef dmaInitUpdate; + DMA_Stream_TypeDef *streamUpdate; + uint32_t dmaItUpdate; + uint16_t dmaSource; + struct stm32_irq irq; +}; + +void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pios_ws2811_pin_cfg *ws2811_pin_cfg); + +void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update); +void PIOS_WS2811_Update(); + +void PIOS_WS2811_DMA_irq_handler(); + +#endif /* PIOS_WS2811_H_ */ diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c new file mode 100644 index 000000000..068b12b33 --- /dev/null +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -0,0 +1,248 @@ +/** + ****************************************************************************** + * + * @file pios_ws2811.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief A driver for ws2811 rgb led controller. + * this is a plain PiOS port of the very clever solution + * implemented by Omri Iluz in the chibios driver here: + * https://github.com/omriiluz/WS2812B-LED-Driver-ChibiOS + * @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 + */ +#include +#include "pios_ws2811.h" +#include +#include +#include "FreeRTOS.h" +#include "task.h" + +// framebuffer +static ledbuf_t *fb = 0; +// bitmask with pin to be set/reset using dma +static ledbuf_t dmaSource; + +static const struct pios_ws2811_cfg *pios_ws2811_cfg; +static const struct pios_ws2811_pin_cfg *pios_ws2811_pin_cfg; + +static void setupTimer(); +static void setupDMA(); + +// generic wrapper around corresponding SPL functions +static void genericTIM_OCxInit(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct, uint8_t ch); +static void genericTIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload, uint8_t ch); + +// timer creates a 1.25 uS signal, with duty cycle controlled by frame buffer values + +/* Example configuration for REVOLUTION + + +*/ + +/* + * How it works: + * a timer and two channels will produce the timings events: + * timer period will be 1.25us + * Ch1 CC event will be raised at 0.40uS from the beginning of the cycle + * Ch2 CC event will be raised at 0.80uS from the beginning of the cycle + * At cycle init an Update event will be raised. + * + * Three dma streams will handle the output pin as following: + * - streamUpdate dma stream, triggered by update event will produce a logic 1 on the output pin + * - streamCh1 will bring the pin to 0 if framebuffer location is set to dmaSource value to send a "0" bit to WS281x + * - streamCh2 will bring pin to 0 once .8us are passed to send a "1" bit to ws281x + * Once StreamCh1 has finished to send the buffer the IRQ handler will stop the timer. + * + */ + +/** + * @brief Initialize WS2811 Led Driver + * @details Initialize the Led Driver based on passed configuration + * + * @param[in] ws2811_cfg ws2811 driver configuration + * @param[in] ws2811_pin_cfg pin to be used as output + * + */ + +void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pios_ws2811_pin_cfg *ws2811_pin_cfg) +{ + assert_param(ws2811_cfg); + assert_param(ws2811_pin_cfg); + + pios_ws2811_pin_cfg = ws2811_pin_cfg; + pios_ws2811_cfg = ws2811_cfg; + GPIO_Init(pios_ws2811_pin_cfg->gpio, &pios_ws2811_pin_cfg->gpioInit); + + dmaSource = (ledbuf_t)pios_ws2811_pin_cfg->gpioInit.GPIO_Pin; + + fb =(ledbuf_t *) pvPortMalloc(PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); + memset(fb, 0, PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); + + //Setup timers + setupTimer(); + setupDMA(); +} + +void setupTimer(){ + // Stop timer + TIM_Cmd(pios_ws2811_cfg->timer, DISABLE); + // Configure timebase and internal clock + TIM_TimeBaseInit(pios_ws2811_cfg->timer, &pios_ws2811_cfg->timerInit); + TIM_InternalClockConfig(pios_ws2811_cfg->timer); + + genericTIM_OCxPreloadConfig(pios_ws2811_cfg->timer, TIM_OCPreload_Enable, pios_ws2811_cfg->timerCh1); + genericTIM_OCxPreloadConfig(pios_ws2811_cfg->timer, TIM_OCPreload_Enable, pios_ws2811_cfg->timerCh2); + TIM_ARRPreloadConfig(pios_ws2811_cfg->timer, ENABLE); + + // enable outputs + //TIM_CtrlPWMOutputs(pios_ws2811_cfg->timer, ENABLE); + + TIM_DMACmd(pios_ws2811_cfg->timer, pios_ws2811_cfg->dmaSource, ENABLE); + + TIM_OCInitTypeDef oc = { + .TIM_OCMode = TIM_OCMode_PWM1, + .TIM_OutputState = TIM_OutputState_Enable, + .TIM_OutputNState = TIM_OutputNState_Disable, + .TIM_Pulse = 0, + .TIM_OCPolarity = TIM_OCPolarity_High, + .TIM_OCNPolarity = TIM_OCNPolarity_High, + .TIM_OCIdleState = TIM_OCIdleState_Reset, + .TIM_OCNIdleState = TIM_OCNIdleState_Reset, + }; + + // (duty in ticks) / (period in ticks) * 1.25uS (period in S) = 0.40 uS + oc.TIM_Pulse = 40 * PIOS_WS2811_TIM_PERIOD / 125; + genericTIM_OCxInit(pios_ws2811_cfg->timer, &oc, pios_ws2811_cfg->timerCh1); + // (duty in ticks) / (period in ticks) * 1.25uS (period in S) = 0.80 uS + oc.TIM_Pulse = 80 * PIOS_WS2811_TIM_PERIOD / 125; + genericTIM_OCxInit(pios_ws2811_cfg->timer, &oc, pios_ws2811_cfg->timerCh2); +} + +void genericTIM_OCxInit(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct, uint8_t ch){ + switch (ch){ + case 1: + TIM_OC1Init(TIMx, TIM_OCInitStruct); + break; + case 2: + TIM_OC2Init(TIMx, TIM_OCInitStruct); + break; + case 3: + TIM_OC3Init(TIMx, TIM_OCInitStruct); + break; + case 4: + TIM_OC4Init(TIMx, TIM_OCInitStruct); + break; + } +} + +void genericTIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload, uint8_t ch){ + switch (ch){ + case 1: + TIM_OC1PreloadConfig(TIMx, TIM_OCPreload); + break; + case 2: + TIM_OC2PreloadConfig(TIMx, TIM_OCPreload); + break; + case 3: + TIM_OC3PreloadConfig(TIMx, TIM_OCPreload); + break; + case 4: + TIM_OC4PreloadConfig(TIMx, TIM_OCPreload); + break; + } +} + + + +void setupDMA(){ + // Configure Ch1 + DMA_Init(pios_ws2811_cfg->streamCh1, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitCh1); + pios_ws2811_cfg->streamCh1->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; + pios_ws2811_cfg->streamCh1->M0AR= (uint32_t)fb; + + NVIC_Init((NVIC_InitTypeDef *)&(pios_ws2811_cfg->irq.init)); + DMA_ITConfig(pios_ws2811_cfg->streamCh1, DMA_IT_TC, ENABLE); + + + DMA_Init(pios_ws2811_cfg->streamCh2, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitCh2); + pios_ws2811_cfg->streamCh2->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; + pios_ws2811_cfg->streamCh2->M0AR= (uint32_t)&dmaSource; + + DMA_Init(pios_ws2811_cfg->streamUpdate, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitUpdate); + pios_ws2811_cfg->streamUpdate->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRL; + pios_ws2811_cfg->streamUpdate->M0AR= (uint32_t)&dmaSource; + + DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->dmaItCh1); + DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh2, pios_ws2811_cfg->dmaItCh2); + DMA_ClearITPendingBit(pios_ws2811_cfg->streamUpdate, pios_ws2811_cfg->dmaItUpdate); + + DMA_Cmd(pios_ws2811_cfg->streamCh2, ENABLE); + DMA_Cmd(pios_ws2811_cfg->streamCh1, ENABLE); + DMA_Cmd(pios_ws2811_cfg->streamUpdate, ENABLE); + +} + +void setColor(uint8_t color, ledbuf_t *buf) { + uint8_t i; + for (i = 0; i < 8; i++) { + buf[i] = ((color << i) & 0b10000000 ? 0x0 : dmaSource); + } +} + +/** + * Set a led color + * @param c color + * @param led led number + * @param update Perform an update after changing led color + */ +void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) { + if(led > PIOS_WS2811_NUMLEDS) { + return; + } + setColor(c.R, fb + (led * 24)); + setColor(c.G, fb + 8 + (led * 24)); + setColor(c.B, fb + 16 + (led * 24)); + if(update){ + PIOS_WS2811_Update(); + } +} + +/** + * trigger an update cycle if not already running + */ +void PIOS_WS2811_Update(){ + // does not start if framebuffer is not allocated (init has not been called yet) or a transfer is still on going + if(!fb || (pios_ws2811_cfg->timer->CR1 & TIM_CR1_CEN)){ + return; + } + + // reset counters for synchronization + pios_ws2811_cfg->timer->CNT = PIOS_WS2811_TIM_PERIOD - 1; + // Start a new cycle + TIM_Cmd(pios_ws2811_cfg->timer, ENABLE); +} + +/** + * Stop timer once the complete framebuffer has been sent + */ + +void PIOS_WS2811_DMA_irq_handler(){ + TIM_Cmd(pios_ws2811_cfg->timer, DISABLE); + DMA_ClearFlag(pios_ws2811_cfg->streamCh1,pios_ws2811_cfg->irq.flags); +} + diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index c847e00d9..8fa3e4457 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1810,3 +1810,115 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { .data_tx_ep = 1, }; #endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_USB_CDC */ + +#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) + +void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); + +const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, +}; + +const struct pios_ws2811_cfg pios_ws2811_cfg = { + // master mode selection Note: configure TIM_CR2_MMS_2 master mode selection + + .timer = TIM1, + .timerInit = { + .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + // period (1.25 uS per period + .TIM_Period = PIOS_WS2811_TIM_PERIOD, + .TIM_RepetitionCounter = 0x0000, + }, + + .timerCh1 = 1, + .streamCh1 = DMA2_Stream1, + + .timerCh2 = 3, + .streamCh2 = DMA2_Stream6, + + .streamUpdate = DMA2_Stream5, + + // DMA ch1, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812 + .dmaInitCh1 = { + .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_Medium, + }, + .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, + // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. + + .dmaInitCh2 = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_Medium, + }, + .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + // triggered by pwm update event. output high at beginning of signal + .dmaInitUpdate = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_Low + }, + .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + .irq = { + // Note this is the stream ID that triggers interrupts (in this case TX) + .flags = (DMA_IT_TCIF1), + .init = { + .NVIC_IRQChannel = DMA2_Stream1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_WS2811_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_WS2811_DMA_irq_handler(); +} diff --git a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c index 63f13b442..bccf9a4d8 100644 --- a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c +++ b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c @@ -36,7 +36,7 @@ #include #include #include - +#include /* * Pull in the board-specific static HW definitions. * Including .c files is a bit ugly but this allows all of @@ -932,6 +932,7 @@ void PIOS_Board_Init(void) PIOS_MPU6000_Init(pios_spi_gyro_id, 0, &pios_mpu6000_cfg); PIOS_MPU6000_CONFIG_Configure(); #endif + PIOS_WS2811_Init(&pios_ws2811_cfg,&pios_ws2811_pin_cfg); } /** From db9435b5ed7110e4ce5fb07c6f8762acf882713b Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 17:28:49 +0200 Subject: [PATCH 10/58] OP-1312 add a switch to include/exclude the driver --- flight/pios/stm32f4xx/pios_ws2811.c | 5 +++++ flight/targets/boards/discoveryf4bare/board_hw_defs.c | 4 +++- .../boards/discoveryf4bare/firmware/inc/pios_config.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index 068b12b33..a87dae56d 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -26,12 +26,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include + +#ifdef PIOS_INCLUDE_WS2811 + #include "pios_ws2811.h" #include #include #include "FreeRTOS.h" #include "task.h" + // framebuffer static ledbuf_t *fb = 0; // bitmask with pin to be set/reset using dma @@ -246,3 +250,4 @@ void PIOS_WS2811_DMA_irq_handler(){ DMA_ClearFlag(pios_ws2811_cfg->streamCh1,pios_ws2811_cfg->irq.flags); } +#endif //PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index 8fa3e4457..a61fd609d 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1810,7 +1810,8 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { .data_tx_ep = 1, }; #endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_USB_CDC */ - +#ifdef PIOS_INCLUDE_WS2811 +#include #define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); @@ -1922,3 +1923,4 @@ void PIOS_WS2811_irq_handler(void) /* Call into the generic code to handle the IRQ for this specific device */ PIOS_WS2811_DMA_irq_handler(); } +#endif //PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/discoveryf4bare/firmware/inc/pios_config.h b/flight/targets/boards/discoveryf4bare/firmware/inc/pios_config.h index 4d335c8ab..c77e50735 100644 --- a/flight/targets/boards/discoveryf4bare/firmware/inc/pios_config.h +++ b/flight/targets/boards/discoveryf4bare/firmware/inc/pios_config.h @@ -88,6 +88,7 @@ //#define PIOS_INCLUDE_MPXV //#define PIOS_INCLUDE_ETASV3 /* #define PIOS_INCLUDE_HCSR04 */ +#define PIOS_INCLUDE_WS2811 /* PIOS receiver drivers */ #define PIOS_INCLUDE_PWM From 28859d2305f7e7b78008be69ec7db868247ffbee Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 18:39:57 +0200 Subject: [PATCH 11/58] OP-1312 Missing ifdefs on pios_board.c --- .../targets/boards/discoveryf4bare/firmware/pios_board.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c index bccf9a4d8..ee7159705 100644 --- a/flight/targets/boards/discoveryf4bare/firmware/pios_board.c +++ b/flight/targets/boards/discoveryf4bare/firmware/pios_board.c @@ -36,7 +36,6 @@ #include #include #include -#include /* * Pull in the board-specific static HW definitions. * Including .c files is a bit ugly but this allows all of @@ -932,7 +931,11 @@ void PIOS_Board_Init(void) PIOS_MPU6000_Init(pios_spi_gyro_id, 0, &pios_mpu6000_cfg); PIOS_MPU6000_CONFIG_Configure(); #endif - PIOS_WS2811_Init(&pios_ws2811_cfg,&pios_ws2811_pin_cfg); + +#ifdef PIOS_INCLUDE_WS2811 +#include + PIOS_WS2811_Init(&pios_ws2811_cfg, &pios_ws2811_pin_cfg); +#endif // PIOS_INCLUDE_WS2811 } /** From a0b857337fb8146c55a7780369e9901233635d9d Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 18:40:59 +0200 Subject: [PATCH 12/58] OP-1312 Add support for Revolution (right now always active on pin3). Configurability not yet added --- flight/pios/inc/pios_ws2811.h | 18 +-- flight/pios/stm32f4xx/pios_ws2811.c | 120 ++++++++++-------- .../targets/boards/revolution/board_hw_defs.c | 115 +++++++++++++++++ .../revolution/firmware/inc/pios_config.h | 2 + .../boards/revolution/firmware/pios_board.c | 6 + 5 files changed, 197 insertions(+), 64 deletions(-) diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h index 0e660bdb0..4dd0efaf9 100644 --- a/flight/pios/inc/pios_ws2811.h +++ b/flight/pios/inc/pios_ws2811.h @@ -38,11 +38,11 @@ #define sign(x) ((x > 0) - (x < 0)) -#define PIOS_WS2811_NUMLEDS 2 -#define PIOS_WS2811_BUFFER_SIZE (((PIOS_WS2811_NUMLEDS) * 24)) +#define PIOS_WS2811_NUMLEDS 2 +#define PIOS_WS2811_BUFFER_SIZE (((PIOS_WS2811_NUMLEDS) * 24)) #define PIOS_WS2811_MEMORYDATASIZE DMA_MemoryDataSize_HalfWord #define PIOS_WS2811_PERIPHERALDATASIZE DMA_PeripheralDataSize_HalfWord -#define PIOS_WS2811_TIM_PERIOD 20 +#define PIOS_WS2811_TIM_PERIOD 20 typedef uint16_t ledbuf_t; @@ -52,7 +52,7 @@ struct Color { uint8_t G; uint8_t B; }; -struct pios_ws2811_pin_cfg{ +struct pios_ws2811_pin_cfg { GPIO_TypeDef *gpio; GPIO_InitTypeDef gpioInit; }; @@ -64,17 +64,17 @@ struct pios_ws2811_cfg { DMA_InitTypeDef dmaInitCh1; DMA_Stream_TypeDef *streamCh1; - uint32_t dmaItCh1; + uint32_t dmaItCh1; DMA_InitTypeDef dmaInitCh2; DMA_Stream_TypeDef *streamCh2; - uint32_t dmaItCh2; + uint32_t dmaItCh2; DMA_InitTypeDef dmaInitUpdate; DMA_Stream_TypeDef *streamUpdate; - uint32_t dmaItUpdate; - uint16_t dmaSource; - struct stm32_irq irq; + uint32_t dmaItUpdate; + uint16_t dmaSource; + struct stm32_irq irq; }; void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pios_ws2811_pin_cfg *ws2811_pin_cfg); diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index a87dae56d..fea91a73d 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -48,15 +48,15 @@ static void setupTimer(); static void setupDMA(); // generic wrapper around corresponding SPL functions -static void genericTIM_OCxInit(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct, uint8_t ch); -static void genericTIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload, uint8_t ch); +static void genericTIM_OCxInit(TIM_TypeDef *TIMx, const TIM_OCInitTypeDef *TIM_OCInitStruct, uint8_t ch); +static void genericTIM_OCxPreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload, uint8_t ch); // timer creates a 1.25 uS signal, with duty cycle controlled by frame buffer values /* Example configuration for REVOLUTION -*/ + */ /* * How it works: @@ -89,20 +89,24 @@ void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pio assert_param(ws2811_pin_cfg); pios_ws2811_pin_cfg = ws2811_pin_cfg; - pios_ws2811_cfg = ws2811_cfg; + pios_ws2811_cfg = ws2811_cfg; GPIO_Init(pios_ws2811_pin_cfg->gpio, &pios_ws2811_pin_cfg->gpioInit); dmaSource = (ledbuf_t)pios_ws2811_pin_cfg->gpioInit.GPIO_Pin; - fb =(ledbuf_t *) pvPortMalloc(PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); + fb = (ledbuf_t *)pvPortMalloc(PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); memset(fb, 0, PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); - - //Setup timers + Color ledoff = { 0, 0, 0 }; + for (uint8_t i = 0; i < PIOS_WS2811_NUMLEDS; i++) { + PIOS_WS2811_setColorRGB(ledoff, i, false); + } + // Setup timers setupTimer(); setupDMA(); } -void setupTimer(){ +void setupTimer() +{ // Stop timer TIM_Cmd(pios_ws2811_cfg->timer, DISABLE); // Configure timebase and internal clock @@ -114,7 +118,7 @@ void setupTimer(){ TIM_ARRPreloadConfig(pios_ws2811_cfg->timer, ENABLE); // enable outputs - //TIM_CtrlPWMOutputs(pios_ws2811_cfg->timer, ENABLE); + // TIM_CtrlPWMOutputs(pios_ws2811_cfg->timer, ENABLE); TIM_DMACmd(pios_ws2811_cfg->timer, pios_ws2811_cfg->dmaSource, ENABLE); @@ -137,59 +141,61 @@ void setupTimer(){ genericTIM_OCxInit(pios_ws2811_cfg->timer, &oc, pios_ws2811_cfg->timerCh2); } -void genericTIM_OCxInit(TIM_TypeDef* TIMx, const TIM_OCInitTypeDef* TIM_OCInitStruct, uint8_t ch){ - switch (ch){ - case 1: - TIM_OC1Init(TIMx, TIM_OCInitStruct); - break; - case 2: - TIM_OC2Init(TIMx, TIM_OCInitStruct); - break; - case 3: - TIM_OC3Init(TIMx, TIM_OCInitStruct); - break; - case 4: - TIM_OC4Init(TIMx, TIM_OCInitStruct); - break; +void genericTIM_OCxInit(TIM_TypeDef *TIMx, const TIM_OCInitTypeDef *TIM_OCInitStruct, uint8_t ch) +{ + switch (ch) { + case 1: + TIM_OC1Init(TIMx, TIM_OCInitStruct); + break; + case 2: + TIM_OC2Init(TIMx, TIM_OCInitStruct); + break; + case 3: + TIM_OC3Init(TIMx, TIM_OCInitStruct); + break; + case 4: + TIM_OC4Init(TIMx, TIM_OCInitStruct); + break; } } -void genericTIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload, uint8_t ch){ - switch (ch){ - case 1: - TIM_OC1PreloadConfig(TIMx, TIM_OCPreload); - break; - case 2: - TIM_OC2PreloadConfig(TIMx, TIM_OCPreload); - break; - case 3: - TIM_OC3PreloadConfig(TIMx, TIM_OCPreload); - break; - case 4: - TIM_OC4PreloadConfig(TIMx, TIM_OCPreload); - break; +void genericTIM_OCxPreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload, uint8_t ch) +{ + switch (ch) { + case 1: + TIM_OC1PreloadConfig(TIMx, TIM_OCPreload); + break; + case 2: + TIM_OC2PreloadConfig(TIMx, TIM_OCPreload); + break; + case 3: + TIM_OC3PreloadConfig(TIMx, TIM_OCPreload); + break; + case 4: + TIM_OC4PreloadConfig(TIMx, TIM_OCPreload); + break; } } - -void setupDMA(){ +void setupDMA() +{ // Configure Ch1 DMA_Init(pios_ws2811_cfg->streamCh1, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitCh1); - pios_ws2811_cfg->streamCh1->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; - pios_ws2811_cfg->streamCh1->M0AR= (uint32_t)fb; + pios_ws2811_cfg->streamCh1->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; + pios_ws2811_cfg->streamCh1->M0AR = (uint32_t)fb; NVIC_Init((NVIC_InitTypeDef *)&(pios_ws2811_cfg->irq.init)); DMA_ITConfig(pios_ws2811_cfg->streamCh1, DMA_IT_TC, ENABLE); DMA_Init(pios_ws2811_cfg->streamCh2, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitCh2); - pios_ws2811_cfg->streamCh2->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; - pios_ws2811_cfg->streamCh2->M0AR= (uint32_t)&dmaSource; + pios_ws2811_cfg->streamCh2->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; + pios_ws2811_cfg->streamCh2->M0AR = (uint32_t)&dmaSource; DMA_Init(pios_ws2811_cfg->streamUpdate, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitUpdate); - pios_ws2811_cfg->streamUpdate->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRL; - pios_ws2811_cfg->streamUpdate->M0AR= (uint32_t)&dmaSource; + pios_ws2811_cfg->streamUpdate->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRL; + pios_ws2811_cfg->streamUpdate->M0AR = (uint32_t)&dmaSource; DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->dmaItCh1); DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh2, pios_ws2811_cfg->dmaItCh2); @@ -198,11 +204,12 @@ void setupDMA(){ DMA_Cmd(pios_ws2811_cfg->streamCh2, ENABLE); DMA_Cmd(pios_ws2811_cfg->streamCh1, ENABLE); DMA_Cmd(pios_ws2811_cfg->streamUpdate, ENABLE); - } -void setColor(uint8_t color, ledbuf_t *buf) { +void setColor(uint8_t color, ledbuf_t *buf) +{ uint8_t i; + for (i = 0; i < 8; i++) { buf[i] = ((color << i) & 0b10000000 ? 0x0 : dmaSource); } @@ -214,14 +221,15 @@ void setColor(uint8_t color, ledbuf_t *buf) { * @param led led number * @param update Perform an update after changing led color */ -void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) { - if(led > PIOS_WS2811_NUMLEDS) { +void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) +{ + if (led > PIOS_WS2811_NUMLEDS) { return; } setColor(c.R, fb + (led * 24)); setColor(c.G, fb + 8 + (led * 24)); setColor(c.B, fb + 16 + (led * 24)); - if(update){ + if (update) { PIOS_WS2811_Update(); } } @@ -229,9 +237,10 @@ void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) { /** * trigger an update cycle if not already running */ -void PIOS_WS2811_Update(){ +void PIOS_WS2811_Update() +{ // does not start if framebuffer is not allocated (init has not been called yet) or a transfer is still on going - if(!fb || (pios_ws2811_cfg->timer->CR1 & TIM_CR1_CEN)){ + if (!fb || (pios_ws2811_cfg->timer->CR1 & TIM_CR1_CEN)) { return; } @@ -245,9 +254,10 @@ void PIOS_WS2811_Update(){ * Stop timer once the complete framebuffer has been sent */ -void PIOS_WS2811_DMA_irq_handler(){ +void PIOS_WS2811_DMA_irq_handler() +{ TIM_Cmd(pios_ws2811_cfg->timer, DISABLE); - DMA_ClearFlag(pios_ws2811_cfg->streamCh1,pios_ws2811_cfg->irq.flags); + DMA_ClearFlag(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->irq.flags); } -#endif //PIOS_INCLUDE_WS2811 +#endif // PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 78d106cbc..716d4745b 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -1962,3 +1962,118 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { .data_tx_ep = 1, }; #endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_USB_CDC */ + +#ifdef PIOS_INCLUDE_WS2811 +#include +#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) + +void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); + +const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, +}; + +const struct pios_ws2811_cfg pios_ws2811_cfg = { + // master mode selection Note: configure TIM_CR2_MMS_2 master mode selection + + .timer = TIM1, + .timerInit = { + .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + // period (1.25 uS per period + .TIM_Period = PIOS_WS2811_TIM_PERIOD, + .TIM_RepetitionCounter = 0x0000, + }, + + .timerCh1 = 1, + .streamCh1 = DMA2_Stream1, + + .timerCh2 = 3, + .streamCh2 = DMA2_Stream6, + + .streamUpdate = DMA2_Stream5, + + // DMA ch1, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812 + .dmaInitCh1 = { + .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_VeryHigh, + }, + .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, + // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. + + .dmaInitCh2 = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_VeryHigh, + }, + .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + // triggered by pwm update event. output high at beginning of signal + .dmaInitUpdate = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_High + }, + .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + .irq = { + // Note this is the stream ID that triggers interrupts (in this case TX) + .flags = (DMA_IT_TCIF1), + .init = { + .NVIC_IRQChannel = DMA2_Stream1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_WS2811_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_WS2811_DMA_irq_handler(); +} +#endif // PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/revolution/firmware/inc/pios_config.h b/flight/targets/boards/revolution/firmware/inc/pios_config.h index c60e9a453..50e8f49b5 100644 --- a/flight/targets/boards/revolution/firmware/inc/pios_config.h +++ b/flight/targets/boards/revolution/firmware/inc/pios_config.h @@ -89,6 +89,8 @@ #define PIOS_INCLUDE_ETASV3 #define PIOS_INCLUDE_MS4525DO +#define PIOS_INCLUDE_WS2811 + /* #define PIOS_INCLUDE_HCSR04 */ /* PIOS receiver drivers */ diff --git a/flight/targets/boards/revolution/firmware/pios_board.c b/flight/targets/boards/revolution/firmware/pios_board.c index 14d917b84..fd31d4f1c 100644 --- a/flight/targets/boards/revolution/firmware/pios_board.c +++ b/flight/targets/boards/revolution/firmware/pios_board.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Pull in the board-specific static HW definitions. @@ -945,6 +946,11 @@ void PIOS_Board_Init(void) PIOS_MPU6000_Init(pios_spi_gyro_id, 0, &pios_mpu6000_cfg); PIOS_MPU6000_CONFIG_Configure(); #endif + +#ifdef PIOS_INCLUDE_WS2811 +#include + PIOS_WS2811_Init(&pios_ws2811_cfg, &pios_ws2811_pin_cfg); +#endif // PIOS_INCLUDE_WS2811 } /** From 99f19dd809d178fd0bcd739a8d9ad68329307814 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 19:48:44 +0200 Subject: [PATCH 13/58] OP-1312 Make WS2811 driver configurable. Now output pin may be chosen among all servo outputs and Flexi-io pins 3 and 4 (they are not used for PWM input/output) --- .../targets/boards/revolution/board_hw_defs.c | 81 +++++++++++++++++-- .../boards/revolution/firmware/pios_board.c | 8 +- shared/uavobjectdefinition/hwsettings.xml | 1 + 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 716d4745b..9a48b2cb8 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -1965,23 +1965,88 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { #ifdef PIOS_INCLUDE_WS2811 #include +#include #define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); -const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg = { - .gpio = GPIOA, - .gpioInit = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_OUT, - .GPIO_OType = GPIO_OType_PP, +const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { + [HWSETTINGS_WS2811LED_OUT_SERVOOUT1] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_SERVOOUT2] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_SERVOOUT3] = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_SERVOOUT4] = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_SERVOOUT5] = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_SERVOOUT6] = { + .gpio = GPIOA, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_FLEXIPIN3] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + [HWSETTINGS_WS2811LED_OUT_FLEXIPIN4] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, }, }; const struct pios_ws2811_cfg pios_ws2811_cfg = { // master mode selection Note: configure TIM_CR2_MMS_2 master mode selection - .timer = TIM1, .timerInit = { .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, diff --git a/flight/targets/boards/revolution/firmware/pios_board.c b/flight/targets/boards/revolution/firmware/pios_board.c index fd31d4f1c..0c03f2a38 100644 --- a/flight/targets/boards/revolution/firmware/pios_board.c +++ b/flight/targets/boards/revolution/firmware/pios_board.c @@ -949,7 +949,13 @@ void PIOS_Board_Init(void) #ifdef PIOS_INCLUDE_WS2811 #include - PIOS_WS2811_Init(&pios_ws2811_cfg, &pios_ws2811_pin_cfg); + HwSettingsWS2811LED_OutOptions ws2811_pin_settings; + HwSettingsWS2811LED_OutGet(&ws2811_pin_settings); + + if (ws2811_pin_settings != HWSETTINGS_WS2811LED_OUT_DISABLED && ws2811_pin_settings < NELEMENTS(pios_ws2811_pin_cfg)) { + PIOS_WS2811_Init(&pios_ws2811_cfg, &pios_ws2811_pin_cfg[ws2811_pin_settings]); + } + #endif // PIOS_INCLUDE_WS2811 } diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index a1bc068e8..f005a31ab 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -25,6 +25,7 @@ + From d42debba50b535dfabfd2dee98ba5735f40b1545 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 26 Apr 2014 20:48:30 +0200 Subject: [PATCH 14/58] OP-1302 Remove the special case for Telemetry in Alarm.c and shut up the telemetry warning in telemetry.c when disconnected --- flight/libraries/alarms.c | 5 ++--- flight/modules/Telemetry/telemetry.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/flight/libraries/alarms.c b/flight/libraries/alarms.c index 7f2688a73..5dc3cda2e 100644 --- a/flight/libraries/alarms.c +++ b/flight/libraries/alarms.c @@ -244,7 +244,7 @@ static int32_t hasSeverity(SystemAlarmsAlarmOptions severity) // Go through alarms and check if any are of the given severity or higher for (uint32_t n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n) { - if (n != SYSTEMALARMS_ALARM_TELEMETRY && cast_struct_to_array(alarms, alarms.Actuator)[n] >= severity) { + if (cast_struct_to_array(alarms, alarms.Actuator)[n] >= severity) { xSemaphoreGiveRecursive(lock); return 1; } @@ -272,8 +272,7 @@ SystemAlarmsAlarmOptions AlarmsGetHighestSeverity() // Go through alarms and find the highest severity uint32_t n = 0; while (n < SYSTEMALARMS_ALARM_NUMELEM && highest != SYSTEMALARMS_ALARM_CRITICAL) { - if (n != SYSTEMALARMS_ALARM_TELEMETRY && - cast_struct_to_array(alarmsData, alarmsData.Actuator)[n] > highest) { + if (cast_struct_to_array(alarmsData, alarmsData.Actuator)[n] > highest) { highest = cast_struct_to_array(alarmsData, alarmsData.Actuator)[n]; } n++; diff --git a/flight/modules/Telemetry/telemetry.c b/flight/modules/Telemetry/telemetry.c index 55c201369..d91ef131e 100644 --- a/flight/modules/Telemetry/telemetry.c +++ b/flight/modules/Telemetry/telemetry.c @@ -650,11 +650,10 @@ static void updateTelemetryStats() flightStats.Status = FLIGHTTELEMETRYSTATS_STATUS_DISCONNECTED; } - // Update the telemetry alarm + // TODO: check whether is there any error condition worth raising an alarm + // Disconnection is actually a normal (non)working status so it is not raising alarms anymore. if (flightStats.Status == FLIGHTTELEMETRYSTATS_STATUS_CONNECTED) { AlarmsClear(SYSTEMALARMS_ALARM_TELEMETRY); - } else { - AlarmsSet(SYSTEMALARMS_ALARM_TELEMETRY, SYSTEMALARMS_ALARM_ERROR); } // Update object From 58178ab193717a6147662fce14e40aa002590023 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 27 Apr 2014 19:11:28 +0200 Subject: [PATCH 15/58] OP-1312 Fixed led boundary check and framebuffer color order. --- flight/pios/stm32f4xx/pios_ws2811.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index fea91a73d..3c732c732 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -223,11 +223,11 @@ void setColor(uint8_t color, ledbuf_t *buf) */ void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) { - if (led > PIOS_WS2811_NUMLEDS) { + if (led >= PIOS_WS2811_NUMLEDS) { return; } - setColor(c.R, fb + (led * 24)); - setColor(c.G, fb + 8 + (led * 24)); + setColor(c.G, fb + (led * 24)); + setColor(c.R, fb + 8 + (led * 24)); setColor(c.B, fb + 16 + (led * 24)); if (update) { PIOS_WS2811_Update(); From 4cece04166a375d45e70badb4ab5db3a0de43dcf Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 27 Apr 2014 19:12:36 +0200 Subject: [PATCH 16/58] OP-1312 fix documentation, get rid of stale comments from previous implementations --- flight/pios/stm32f4xx/pios_ws2811.c | 132 +++++++++++++++++- .../boards/discoveryf4bare/board_hw_defs.c | 18 +-- .../targets/boards/revolution/board_hw_defs.c | 25 ++-- 3 files changed, 153 insertions(+), 22 deletions(-) diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index 3c732c732..6dc82b6e8 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -53,10 +53,138 @@ static void genericTIM_OCxPreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreloa // timer creates a 1.25 uS signal, with duty cycle controlled by frame buffer values -/* Example configuration for REVOLUTION +/* Example configuration fragment for REVOLUTION +#ifdef PIOS_INCLUDE_WS2811 +#include +#include +#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) - */ +// interrupt vector for DMA streamCh1 +void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); + +const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { + [HWSETTINGS_WS2811LED_OUT_SERVOOUT1] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + .... + [HWSETTINGS_WS2811LED_OUT_FLEXIPIN4] = { + .gpio = GPIOB, + .gpioInit = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, +}; + +const struct pios_ws2811_cfg pios_ws2811_cfg = { + .timer = TIM1, + .timerInit = { + .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + // period (1.25 uS per period + .TIM_Period = PIOS_WS2811_TIM_PERIOD, + .TIM_RepetitionCounter = 0x0000, + }, + + .timerCh1 = 1, + .streamCh1 = DMA2_Stream1, + .timerCh2 = 3, + .streamCh2 = DMA2_Stream6, + .streamUpdate = DMA2_Stream5, + + // DMA streamCh1, triggered by timerCh1 pwm signal. + // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 + .dmaInitCh1 = { + .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_VeryHigh, + }, + .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, + + // DMA streamCh2, triggered by timerCh2 pwm signal. + // Reset output value late to indicate "1" bit to ws2812. + .dmaInitCh2 = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_VeryHigh, + }, + .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + + // DMA streamUpdate Triggered by timer update event + // Outputs a high logic level at beginning of a cycle + .dmaInitUpdate = { + .DMA_BufferSize = 1, + .DMA_Channel = DMA_Channel_6, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_FIFOMode = DMA_FIFOMode_Enable, + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, + .DMA_Memory0BaseAddr = 0, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, + .DMA_MemoryInc = DMA_MemoryInc_Disable, + .DMA_Mode = DMA_Mode_Circular, + .DMA_PeripheralBaseAddr = 0, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_Priority = DMA_Priority_High + }, + .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + + // DMA streamCh1 interrupt vector, used to block timer at end of framebuffer transfer + .irq = { + .flags = (DMA_IT_TCIF1), + .init = { + .NVIC_IRQChannel = DMA2_Stream1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_WS2811_irq_handler(void) +{ + PIOS_WS2811_DMA_irq_handler(); +} +#endif // PIOS_INCLUDE_WS2811 + +*/ /* * How it works: diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index a61fd609d..04aab420c 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1827,8 +1827,6 @@ const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg = { }; const struct pios_ws2811_cfg pios_ws2811_cfg = { - // master mode selection Note: configure TIM_CR2_MMS_2 master mode selection - .timer = TIM1, .timerInit = { .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, @@ -1841,13 +1839,12 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .timerCh1 = 1, .streamCh1 = DMA2_Stream1, - .timerCh2 = 3, .streamCh2 = DMA2_Stream6, - .streamUpdate = DMA2_Stream5, - // DMA ch1, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812 + // DMA streamCh1, triggered by timerCh1 pwm signal. + // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 .dmaInitCh1 = { .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, .DMA_Channel = DMA_Channel_6, @@ -1866,8 +1863,9 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .DMA_Priority = DMA_Priority_Medium, }, .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, - // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. + // DMA streamCh2, triggered by timerCh2 pwm signal. + // Reset output value late to indicate "1" bit to ws2812. .dmaInitCh2 = { .DMA_BufferSize = 1, .DMA_Channel = DMA_Channel_6, @@ -1886,7 +1884,9 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .DMA_Priority = DMA_Priority_Medium, }, .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, - // triggered by pwm update event. output high at beginning of signal + + // DMA streamUpdate Triggered by timer update event + // Outputs a high logic level at beginning of a cycle .dmaInitUpdate = { .DMA_BufferSize = 1, .DMA_Channel = DMA_Channel_6, @@ -1906,8 +1906,9 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { }, .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + + // DMA streamCh1 interrupt vector, used to block timer at end of framebuffer transfer .irq = { - // Note this is the stream ID that triggers interrupts (in this case TX) .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, @@ -1920,7 +1921,6 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { void PIOS_WS2811_irq_handler(void) { - /* Call into the generic code to handle the IRQ for this specific device */ PIOS_WS2811_DMA_irq_handler(); } #endif //PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 9a48b2cb8..4bc8c7119 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -1969,7 +1969,9 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { #define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); - +// list of pin configurable as ws281x outputs. +// this will not clash with PWM in or servo output as +// pins will be reconfigured as _OUT so the alternate function is disabled. const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { [HWSETTINGS_WS2811LED_OUT_SERVOOUT1] = { .gpio = GPIOB, @@ -2046,7 +2048,6 @@ const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { }; const struct pios_ws2811_cfg pios_ws2811_cfg = { - // master mode selection Note: configure TIM_CR2_MMS_2 master mode selection .timer = TIM1, .timerInit = { .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, @@ -2059,13 +2060,12 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .timerCh1 = 1, .streamCh1 = DMA2_Stream1, - .timerCh2 = 3, .streamCh2 = DMA2_Stream6, - .streamUpdate = DMA2_Stream5, - // DMA ch1, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812 + // DMA streamCh1, triggered by timerCh1 pwm signal. + // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 .dmaInitCh1 = { .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, .DMA_Channel = DMA_Channel_6, @@ -2084,8 +2084,9 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .DMA_Priority = DMA_Priority_VeryHigh, }, .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, - // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. + // DMA streamCh2, triggered by timerCh2 pwm signal. + // Reset output value late to indicate "1" bit to ws2812. .dmaInitCh2 = { .DMA_BufferSize = 1, .DMA_Channel = DMA_Channel_6, @@ -2103,8 +2104,10 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .DMA_PeripheralInc = DMA_PeripheralInc_Disable, .DMA_Priority = DMA_Priority_VeryHigh, }, - .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, - // triggered by pwm update event. output high at beginning of signal + .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + + // DMA streamUpdate Triggered by timer update event + // Outputs a high logic level at beginning of a cycle .dmaInitUpdate = { .DMA_BufferSize = 1, .DMA_Channel = DMA_Channel_6, @@ -2124,8 +2127,9 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { }, .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, - .irq = { - // Note this is the stream ID that triggers interrupts (in this case TX) + + // DMAInitCh1 interrupt vector, used to block timer at end of framebuffer transfer + .irq = { .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, @@ -2138,7 +2142,6 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { void PIOS_WS2811_irq_handler(void) { - /* Call into the generic code to handle the IRQ for this specific device */ PIOS_WS2811_DMA_irq_handler(); } #endif // PIOS_INCLUDE_WS2811 From 3897106f4dd7c24919d7de290e60b81dd68f6cac Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 1 May 2014 10:33:44 +0200 Subject: [PATCH 17/58] OP-1312 remove boilerplate from config using macros. Use four locations for ch1+update dma source to exploit fifo and memory read bursts --- flight/pios/inc/pios_ws2811.h | 54 +++++++++ flight/pios/stm32f4xx/pios_ws2811.c | 103 +++++------------- .../boards/discoveryf4bare/board_hw_defs.c | 76 +++---------- .../targets/boards/revolution/board_hw_defs.c | 62 ++--------- 4 files changed, 103 insertions(+), 192 deletions(-) diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h index 4dd0efaf9..a71c90d87 100644 --- a/flight/pios/inc/pios_ws2811.h +++ b/flight/pios/inc/pios_ws2811.h @@ -44,6 +44,60 @@ #define PIOS_WS2811_PERIPHERALDATASIZE DMA_PeripheralDataSize_HalfWord #define PIOS_WS2811_TIM_PERIOD 20 +#define PIOS_WS2811_DMA_CH1_CONFIG(channel) \ + { \ + .DMA_BufferSize = 4, \ + .DMA_Channel = channel, \ + .DMA_DIR = DMA_DIR_MemoryToPeripheral, \ + .DMA_FIFOMode = DMA_FIFOMode_Enable, \ + .DMA_FIFOThreshold = DMA_FIFOThreshold_Full, \ + .DMA_Memory0BaseAddr = 0, \ + .DMA_MemoryBurst = DMA_MemoryBurst_INC4, \ + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, \ + .DMA_MemoryInc = DMA_MemoryInc_Enable, \ + .DMA_Mode = DMA_Mode_Circular, \ + .DMA_PeripheralBaseAddr = 0, \ + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, \ + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, \ + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, \ + .DMA_Priority = DMA_Priority_VeryHigh, } + +#define PIOS_WS2811_DMA_CH2_CONFIG(channel) \ + { \ + .DMA_BufferSize = 4, \ + .DMA_Channel = channel, \ + .DMA_DIR = DMA_DIR_MemoryToPeripheral, \ + .DMA_FIFOMode = DMA_FIFOMode_Enable, \ + .DMA_FIFOThreshold = DMA_FIFOThreshold_Full, \ + .DMA_Memory0BaseAddr = 0, \ + .DMA_MemoryBurst = DMA_MemoryBurst_INC4, \ + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, \ + .DMA_MemoryInc = DMA_MemoryInc_Enable, \ + .DMA_Mode = DMA_Mode_Circular, \ + .DMA_PeripheralBaseAddr = 0, \ + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, \ + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, \ + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, \ + .DMA_Priority = DMA_Priority_High } + +#define PIOS_WS2811_DMA_UPDATE_CONFIG(channel) \ + { \ + .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, \ + .DMA_Channel = channel, \ + .DMA_DIR = DMA_DIR_MemoryToPeripheral, \ + .DMA_FIFOMode = DMA_FIFOMode_Enable, \ + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, \ + .DMA_Memory0BaseAddr = 0, \ + .DMA_MemoryBurst = DMA_MemoryBurst_INC4, \ + .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, \ + .DMA_MemoryInc = DMA_MemoryInc_Enable, \ + .DMA_Mode = DMA_Mode_Circular, \ + .DMA_PeripheralBaseAddr = 0, \ + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, \ + .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, \ + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, \ + .DMA_Priority = DMA_Priority_VeryHigh, } + typedef uint16_t ledbuf_t; typedef struct Color Color; diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index 6dc82b6e8..b3933ce26 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -39,7 +39,7 @@ // framebuffer static ledbuf_t *fb = 0; // bitmask with pin to be set/reset using dma -static ledbuf_t dmaSource; +static ledbuf_t dmaSource[4]; static const struct pios_ws2811_cfg *pios_ws2811_cfg; static const struct pios_ws2811_pin_cfg *pios_ws2811_pin_cfg; @@ -55,15 +55,15 @@ static void genericTIM_OCxPreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreloa /* Example configuration fragment for REVOLUTION -#ifdef PIOS_INCLUDE_WS2811 -#include -#include -#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) + #ifdef PIOS_INCLUDE_WS2811 + #include + #include + #define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) -// interrupt vector for DMA streamCh1 -void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); + // interrupt vector for DMA streamCh1 + void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); -const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { + const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { [HWSETTINGS_WS2811LED_OUT_SERVOOUT1] = { .gpio = GPIOB, .gpioInit = { @@ -83,9 +83,9 @@ const struct pios_ws2811_pin_cfg pios_ws2811_pin_cfg[] = { .GPIO_OType = GPIO_OType_PP, }, }, -}; + }; -const struct pios_ws2811_cfg pios_ws2811_cfg = { + const struct pios_ws2811_cfg pios_ws2811_cfg = { .timer = TIM1, .timerInit = { .TIM_Prescaler = PIOS_WS2811_TIM_DIVIDER - 1, @@ -104,67 +104,19 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { // DMA streamCh1, triggered by timerCh1 pwm signal. // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 - .dmaInitCh1 = { - .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_VeryHigh, - }, + .dmaInitCh1 = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, // DMA streamCh2, triggered by timerCh2 pwm signal. // Reset output value late to indicate "1" bit to ws2812. - .dmaInitCh2 = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_VeryHigh, - }, - .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + .dmaInitCh2 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), + .dmaItCh2 = DMA_IT_TEIF6 | DMA_IT_TCIF6, // DMA streamUpdate Triggered by timer update event // Outputs a high logic level at beginning of a cycle - .dmaInitUpdate = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_High - }, - .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, - .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + .dmaInitUpdate = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), + .dmaItUpdate = DMA_IT_TEIF5 | DMA_IT_TCIF5, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, // DMA streamCh1 interrupt vector, used to block timer at end of framebuffer transfer .irq = { @@ -176,15 +128,15 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .NVIC_IRQChannelCmd = ENABLE, }, }, -}; + }; -void PIOS_WS2811_irq_handler(void) -{ + void PIOS_WS2811_irq_handler(void) + { PIOS_WS2811_DMA_irq_handler(); -} -#endif // PIOS_INCLUDE_WS2811 + } + #endif // PIOS_INCLUDE_WS2811 -*/ + */ /* * How it works: @@ -219,8 +171,9 @@ void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pio pios_ws2811_pin_cfg = ws2811_pin_cfg; pios_ws2811_cfg = ws2811_cfg; GPIO_Init(pios_ws2811_pin_cfg->gpio, &pios_ws2811_pin_cfg->gpioInit); - - dmaSource = (ledbuf_t)pios_ws2811_pin_cfg->gpioInit.GPIO_Pin; + for (uint8_t i = 0; i < 4; i++) { + dmaSource[i] = (ledbuf_t)pios_ws2811_pin_cfg->gpioInit.GPIO_Pin; + } fb = (ledbuf_t *)pvPortMalloc(PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); memset(fb, 0, PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); @@ -319,11 +272,11 @@ void setupDMA() DMA_Init(pios_ws2811_cfg->streamCh2, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitCh2); pios_ws2811_cfg->streamCh2->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRH; - pios_ws2811_cfg->streamCh2->M0AR = (uint32_t)&dmaSource; + pios_ws2811_cfg->streamCh2->M0AR = (uint32_t)dmaSource; DMA_Init(pios_ws2811_cfg->streamUpdate, (DMA_InitTypeDef *)&pios_ws2811_cfg->dmaInitUpdate); pios_ws2811_cfg->streamUpdate->PAR = (uint32_t)&pios_ws2811_pin_cfg->gpio->BSRRL; - pios_ws2811_cfg->streamUpdate->M0AR = (uint32_t)&dmaSource; + pios_ws2811_cfg->streamUpdate->M0AR = (uint32_t)dmaSource; DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->dmaItCh1); DMA_ClearITPendingBit(pios_ws2811_cfg->streamCh2, pios_ws2811_cfg->dmaItCh2); @@ -339,7 +292,7 @@ void setColor(uint8_t color, ledbuf_t *buf) uint8_t i; for (i = 0; i < 8; i++) { - buf[i] = ((color << i) & 0b10000000 ? 0x0 : dmaSource); + buf[i] = ((color << i) & 0b10000000 ? 0x0 : dmaSource[0]); } } diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index 04aab420c..12346e158 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -55,7 +55,7 @@ static const struct pios_gpio pios_leds[] = { }, .active_low = false }, - [PIOS_LED_D1] = { + [PIOS_LED_D1] = { .pin = { .gpio = GPIOD, .init = { @@ -68,7 +68,7 @@ static const struct pios_gpio pios_leds[] = { }, .active_low = false }, - [PIOS_LED_D2] = { + [PIOS_LED_D2] = { .pin = { .gpio = GPIOD, .init = { @@ -91,7 +91,7 @@ static const struct pios_gpio_cfg pios_led_cfg = { const struct pios_gpio_cfg *PIOS_BOARD_HW_DEFS_GetLedCfg(__attribute__((unused)) uint32_t board_revision) { - return &pios_led_cfg; + return &pios_led_cfg; } #endif /* PIOS_INCLUDE_LED */ @@ -1812,7 +1812,7 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { #endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_USB_CDC */ #ifdef PIOS_INCLUDE_WS2811 #include -#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) +#define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) void DMA2_Stream1_IRQHandler(void) __attribute__((alias("PIOS_WS2811_irq_handler"))); @@ -1833,7 +1833,7 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .TIM_ClockDivision = TIM_CKD_DIV1, .TIM_CounterMode = TIM_CounterMode_Up, // period (1.25 uS per period - .TIM_Period = PIOS_WS2811_TIM_PERIOD, + .TIM_Period = PIOS_WS2811_TIM_PERIOD, .TIM_RepetitionCounter = 0x0000, }, @@ -1845,70 +1845,22 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { // DMA streamCh1, triggered by timerCh1 pwm signal. // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 - .dmaInitCh1 = { - .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_Medium, - }, - .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, + .dmaInitCh1 = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), + .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, // DMA streamCh2, triggered by timerCh2 pwm signal. // Reset output value late to indicate "1" bit to ws2812. - .dmaInitCh2 = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_Medium, - }, - .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + .dmaInitCh2 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), + .dmaItCh2 = DMA_IT_TEIF6 | DMA_IT_TCIF6, // DMA streamUpdate Triggered by timer update event // Outputs a high logic level at beginning of a cycle - .dmaInitUpdate = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_Low - }, - .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, - .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + .dmaInitUpdate = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), + .dmaItUpdate = DMA_IT_TEIF5 | DMA_IT_TCIF5, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, // DMA streamCh1 interrupt vector, used to block timer at end of framebuffer transfer - .irq = { + .irq = { .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, @@ -1923,4 +1875,4 @@ void PIOS_WS2811_irq_handler(void) { PIOS_WS2811_DMA_irq_handler(); } -#endif //PIOS_INCLUDE_WS2811 +#endif // PIOS_INCLUDE_WS2811 diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 4bc8c7119..dbb6e8692 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -2066,70 +2066,22 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { // DMA streamCh1, triggered by timerCh1 pwm signal. // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 - .dmaInitCh1 = { - .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_VeryHigh, - }, + .dmaInitCh1 = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, // DMA streamCh2, triggered by timerCh2 pwm signal. // Reset output value late to indicate "1" bit to ws2812. - .dmaInitCh2 = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_VeryHigh, - }, - .dmaItCh2 = DMA_IT_TEIF2 | DMA_IT_TCIF2, + .dmaInitCh2 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), + .dmaItCh2 = DMA_IT_TEIF6 | DMA_IT_TCIF6, // DMA streamUpdate Triggered by timer update event // Outputs a high logic level at beginning of a cycle - .dmaInitUpdate = { - .DMA_BufferSize = 1, - .DMA_Channel = DMA_Channel_6, - .DMA_DIR = DMA_DIR_MemoryToPeripheral, - .DMA_FIFOMode = DMA_FIFOMode_Enable, - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, - .DMA_Memory0BaseAddr = 0, - .DMA_MemoryBurst = DMA_MemoryBurst_Single, - .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, - .DMA_MemoryInc = DMA_MemoryInc_Disable, - .DMA_Mode = DMA_Mode_Circular, - .DMA_PeripheralBaseAddr = 0, - .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, - .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_Priority = DMA_Priority_High - }, - .dmaItUpdate = DMA_IT_TEIF6 | DMA_IT_TCIF6, - .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, + .dmaInitUpdate = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), + .dmaItUpdate = DMA_IT_TEIF5 | DMA_IT_TCIF5, + .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, // DMAInitCh1 interrupt vector, used to block timer at end of framebuffer transfer - .irq = { + .irq = { .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, From 19caa57dc618d2e102781a592fa0a32f52525e08 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sat, 3 May 2014 11:45:30 +0200 Subject: [PATCH 18/58] OP-1312 fix copy/paste-naming issue --- flight/pios/inc/pios_ws2811.h | 13 +++++++------ .../targets/boards/discoveryf4bare/board_hw_defs.c | 6 +++--- flight/targets/boards/revolution/board_hw_defs.c | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h index a71c90d87..65f84a59a 100644 --- a/flight/pios/inc/pios_ws2811.h +++ b/flight/pios/inc/pios_ws2811.h @@ -46,11 +46,11 @@ #define PIOS_WS2811_DMA_CH1_CONFIG(channel) \ { \ - .DMA_BufferSize = 4, \ + .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, \ .DMA_Channel = channel, \ .DMA_DIR = DMA_DIR_MemoryToPeripheral, \ .DMA_FIFOMode = DMA_FIFOMode_Enable, \ - .DMA_FIFOThreshold = DMA_FIFOThreshold_Full, \ + .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, \ .DMA_Memory0BaseAddr = 0, \ .DMA_MemoryBurst = DMA_MemoryBurst_INC4, \ .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, \ @@ -78,15 +78,15 @@ .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, \ .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, \ .DMA_PeripheralInc = DMA_PeripheralInc_Disable, \ - .DMA_Priority = DMA_Priority_High } + .DMA_Priority = DMA_Priority_VeryHigh, } #define PIOS_WS2811_DMA_UPDATE_CONFIG(channel) \ { \ - .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, \ + .DMA_BufferSize = 4, \ .DMA_Channel = channel, \ .DMA_DIR = DMA_DIR_MemoryToPeripheral, \ .DMA_FIFOMode = DMA_FIFOMode_Enable, \ - .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, \ + .DMA_FIFOThreshold = DMA_FIFOThreshold_Full, \ .DMA_Memory0BaseAddr = 0, \ .DMA_MemoryBurst = DMA_MemoryBurst_INC4, \ .DMA_MemoryDataSize = PIOS_WS2811_MEMORYDATASIZE, \ @@ -96,7 +96,8 @@ .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, \ .DMA_PeripheralDataSize = PIOS_WS2811_PERIPHERALDATASIZE, \ .DMA_PeripheralInc = DMA_PeripheralInc_Disable, \ - .DMA_Priority = DMA_Priority_VeryHigh, } + .DMA_Priority = DMA_Priority_High } + typedef uint16_t ledbuf_t; diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index 12346e158..73ca21c81 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1845,17 +1845,17 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { // DMA streamCh1, triggered by timerCh1 pwm signal. // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 - .dmaInitCh1 = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), + .dmaInitCh1 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, // DMA streamCh2, triggered by timerCh2 pwm signal. // Reset output value late to indicate "1" bit to ws2812. - .dmaInitCh2 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), + .dmaInitCh2 = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), .dmaItCh2 = DMA_IT_TEIF6 | DMA_IT_TCIF6, // DMA streamUpdate Triggered by timer update event // Outputs a high logic level at beginning of a cycle - .dmaInitUpdate = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), + .dmaInitUpdate = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), .dmaItUpdate = DMA_IT_TEIF5 | DMA_IT_TCIF5, .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index dbb6e8692..13a202091 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -2066,17 +2066,17 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { // DMA streamCh1, triggered by timerCh1 pwm signal. // if FrameBuffer indicates, reset output value early to indicate "0" bit to ws2812 - .dmaInitCh1 = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), + .dmaInitCh1 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), .dmaItCh1 = DMA_IT_TEIF1 | DMA_IT_TCIF1, // DMA streamCh2, triggered by timerCh2 pwm signal. // Reset output value late to indicate "1" bit to ws2812. - .dmaInitCh2 = PIOS_WS2811_DMA_CH1_CONFIG(DMA_Channel_6), + .dmaInitCh2 = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), .dmaItCh2 = DMA_IT_TEIF6 | DMA_IT_TCIF6, // DMA streamUpdate Triggered by timer update event // Outputs a high logic level at beginning of a cycle - .dmaInitUpdate = PIOS_WS2811_DMA_CH2_CONFIG(DMA_Channel_6), + .dmaInitUpdate = PIOS_WS2811_DMA_UPDATE_CONFIG(DMA_Channel_6), .dmaItUpdate = DMA_IT_TEIF5 | DMA_IT_TCIF5, .dmaSource = TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_Update, From 764520980981f49b9988138b1c82fa20db0cf362 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 7 May 2014 20:11:24 +0200 Subject: [PATCH 19/58] OP-1329 Various fixes to airspeed: - Prevent Airspeed module with Sensor=none from constantly running and updating AirspeedSensor - Do not call gps_airspeedInitialize if not needed --- flight/modules/Airspeed/airspeed.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/flight/modules/Airspeed/airspeed.c b/flight/modules/Airspeed/airspeed.c index 8f368bef7..92fe7bcf7 100644 --- a/flight/modules/Airspeed/airspeed.c +++ b/flight/modules/Airspeed/airspeed.c @@ -137,17 +137,14 @@ MODULE_INITCALL(AirspeedInitialize, AirspeedStart); static void airspeedTask(__attribute__((unused)) void *parameters) { AirspeedSettingsUpdatedCb(AirspeedSettingsHandle()); - + bool gpsAirspeedInitialized = false; AirspeedSensorData airspeedData; AirspeedSensorGet(&airspeedData); AirspeedSettingsUpdatedCb(NULL); - gps_airspeedInitialize(); - airspeedData.SensorConnected = AIRSPEEDSENSOR_SENSORCONNECTED_FALSE; - // Main task loop portTickType lastSysTime = xTaskGetTickCount(); while (1) { @@ -161,7 +158,12 @@ static void airspeedTask(__attribute__((unused)) void *parameters) AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); lastAirspeedSensorType = airspeedSettings.AirspeedSensorType; } - + if(airspeedSettings.AirspeedSensorType == AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE){ + // no need to check so often until a sensor is enabled + AirspeedAlarm(SYSTEMALARMS_ALARM_DEFAULT); + vTaskDelay(5000/ portTICK_RATE_MS); + continue; + } switch (airspeedSettings.AirspeedSensorType) { #if defined(PIOS_INCLUDE_MPXV) case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002: @@ -183,6 +185,10 @@ static void airspeedTask(__attribute__((unused)) void *parameters) break; #endif case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GROUNDSPEEDBASEDWINDESTIMATION: + if(!gpsAirspeedInitialized){ + gpsAirspeedInitialized = true; + gps_airspeedInitialize(); + } gps_airspeedGet(&airspeedData, &airspeedSettings); break; case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE: From 8462adb579ac40b1191a9683805bf8e7da6f21a9 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 7 May 2014 20:20:19 +0200 Subject: [PATCH 20/58] OP-1330 Delay SetHomeLocation call from GPS module to be able to save HomeLocation.Set=false --- flight/modules/GPS/GPS.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index 420f9599c..402c1d55e 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -64,7 +64,10 @@ static float GravityAccel(float latitude, float longitude, float altitude); // Private constants #define GPS_TIMEOUT_MS 500 - +// delay from detecting HomeLocation.Set == False before setting new homelocation +// this prevent that a save with homelocation.Set = false triggered by gps ends saving +// the new location with Set = true. +#define HOMELOCATIONSETDELAY 5000 #ifdef PIOS_GPS_SETS_HOMELOCATION // Unfortunately need a good size stack for the WMM calculation @@ -199,7 +202,7 @@ static void gpsTask(__attribute__((unused)) void *parameters) { portTickType xDelay = 100 / portTICK_RATE_MS; uint32_t timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS; - + portTickType homelocationSetDelay = 0; GPSPositionSensorData gpspositionsensor; GPSSettingsData gpsSettings; @@ -260,7 +263,13 @@ static void gpsTask(__attribute__((unused)) void *parameters) HomeLocationGet(&home); if (home.Set == HOMELOCATION_SET_FALSE) { - setHomeLocation(&gpspositionsensor); + if(homelocationSetDelay == 0){ + homelocationSetDelay = xTaskGetTickCount(); + } + if(xTaskGetTickCount() - homelocationSetDelay > HOMELOCATIONSETDELAY){ + setHomeLocation(&gpspositionsensor); + homelocationSetDelay = 0; + } } #endif } else if ((gpspositionsensor.Status == GPSPOSITIONSENSOR_STATUS_FIX3D) && From 2ceef9ce864087306a3bd360543093ddbba168c1 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 7 May 2014 22:47:50 +0200 Subject: [PATCH 21/58] OP-1326 Change default airspeed sensor to "None" --- shared/uavobjectdefinition/airspeedsettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/uavobjectdefinition/airspeedsettings.xml b/shared/uavobjectdefinition/airspeedsettings.xml index fbfce3e91..0c438afa5 100644 --- a/shared/uavobjectdefinition/airspeedsettings.xml +++ b/shared/uavobjectdefinition/airspeedsettings.xml @@ -4,7 +4,7 @@ - + From 516f359645f4bebf19143977c7762ed11636a940 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 7 May 2014 23:23:51 +0200 Subject: [PATCH 22/58] OP-1329 fix a cherry-pick issue --- flight/modules/Airspeed/airspeed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/modules/Airspeed/airspeed.c b/flight/modules/Airspeed/airspeed.c index 92fe7bcf7..9aba9fb72 100644 --- a/flight/modules/Airspeed/airspeed.c +++ b/flight/modules/Airspeed/airspeed.c @@ -160,7 +160,7 @@ static void airspeedTask(__attribute__((unused)) void *parameters) } if(airspeedSettings.AirspeedSensorType == AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE){ // no need to check so often until a sensor is enabled - AirspeedAlarm(SYSTEMALARMS_ALARM_DEFAULT); + AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); vTaskDelay(5000/ portTICK_RATE_MS); continue; } From 07a828f971c365ef6871270cfce0af54bf7d98d3 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Thu, 8 May 2014 17:55:20 +0200 Subject: [PATCH 23/58] OP-1331 OP-1335 Added support in ConfigTaskWidget to bind a GComboBox to an integer property --- .../uavobjectwidgetutils/configtaskwidget.cpp | 50 ++++++++++++------- .../uavobjectwidgetutils/configtaskwidget.h | 5 +- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index 156dd26e8..bc0a52f6d 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -58,7 +58,7 @@ void ConfigTaskWidget::addUAVObject(QString objectName, QList *reloadGroups void ConfigTaskWidget::addUAVObject(UAVObject *objectName, QList *reloadGroups) { - addUAVObject(objectName ? objectName->getName() : QString(""), reloadGroups); + addUAVObject(objectName ? objectName->getName() : QString(), reloadGroups); } int ConfigTaskWidget::fieldIndexFromElementName(QString objectName, QString fieldName, QString elementName) @@ -84,7 +84,7 @@ void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, Q void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, QString elementName) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, elementName); + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, elementName); } void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, QWidget *widget, QString elementName, double scale, @@ -97,14 +97,14 @@ void ConfigTaskWidget::addWidgetBinding(QString objectName, QString fieldName, Q void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, QString elementName, double scale, bool isLimited, QList *reloadGroupIDs, quint32 instID) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, elementName, scale, + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, elementName, scale, isLimited, reloadGroupIDs, instID); } void ConfigTaskWidget::addWidgetBinding(UAVObject *object, UAVObjectField *field, QWidget *widget, int index, double scale, bool isLimited, QList *reloadGroupIDs, quint32 instID) { - addWidgetBinding(object ? object->getName() : QString(""), field ? field->getName() : QString(""), widget, index, scale, + addWidgetBinding(object ? object->getName() : QString(), field ? field->getName() : QString(), widget, index, scale, isLimited, reloadGroupIDs, instID); } @@ -146,7 +146,6 @@ void ConfigTaskWidget::doAddWidgetBinding(QString objectName, QString fieldName, binding->setIsEnabled(m_widgetBindingsPerWidget.count(widget) == 0); m_widgetBindingsPerWidget.insert(widget, binding); - if (object) { m_widgetBindingsPerObject.insert(object, binding); if (m_saveButton) { @@ -264,7 +263,8 @@ void ConfigTaskWidget::onAutopilotDisconnect() invalidateObjects(); } -void ConfigTaskWidget::forceConnectedState() // dynamic widgets don't recieve the connected signal. This should be called instead. +// dynamic widgets don't recieve the connected signal. This should be called instead. +void ConfigTaskWidget::forceConnectedState() { m_isConnected = true; setDirty(false); @@ -385,7 +385,7 @@ void ConfigTaskWidget::forceShadowUpdates() if (!binding->isEnabled()) { continue; } - QVariant widgetValue = getVariantFromWidget(binding->widget(), binding->scale(), binding->units()); + QVariant widgetValue = getVariantFromWidget(binding->widget(), binding->scale(), binding->units(), binding->type()); foreach(ShadowWidgetBinding * shadow, binding->shadows()) { disconnectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); @@ -412,17 +412,17 @@ void ConfigTaskWidget::widgetsContentsChanged() if (binding->widget() == emitter) { scale = binding->scale(); checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), - getVariantFromWidget(emitter, scale, binding->units()), scale); + getVariantFromWidget(emitter, scale, binding->units(), binding->type()), scale); } else { foreach(ShadowWidgetBinding * shadow, binding->shadows()) { if (shadow->widget() == emitter) { scale = shadow->scale(); checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), - getVariantFromWidget(emitter, scale, binding->units()), scale); + getVariantFromWidget(emitter, scale, binding->units(), binding->type()), scale); } } } - value = getVariantFromWidget(emitter, scale, binding->units()); + value = getVariantFromWidget(emitter, scale, binding->units(), binding->type()); binding->setValue(value); if (binding->widget() != emitter) { @@ -851,9 +851,12 @@ void ConfigTaskWidget::disconnectWidgetUpdatesToSlot(QWidget *widget, const char } } -QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, QString units) +QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, QString units, QString type) { if (QComboBox * cb = qobject_cast(widget)) { + if (type.startsWith("int") || type.startsWith("uint")) { + return cb->currentIndex(); + } return (QString)cb->currentText(); } else if (QDoubleSpinBox * cb = qobject_cast(widget)) { return (double)(cb->value() * scale); @@ -876,11 +879,16 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, Q } } -bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units) +bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units, QString type) { if (QComboBox * cb = qobject_cast(widget)) { - cb->setCurrentIndex(cb->findText(value.toString())); - return true; + bool ok = true; + if (type.startsWith("int") || type.startsWith("uint")) { + cb->setCurrentIndex(value.toInt(&ok)); + } else { + cb->setCurrentIndex(cb->findText(value.toString())); + } + return ok; } else if (QLabel * cb = qobject_cast(widget)) { if (scale == 0) { cb->setText(value.toString()); @@ -919,7 +927,7 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale) { - return setWidgetFromVariant(widget, value, scale, QString("")); + return setWidgetFromVariant(widget, value, scale, QString(), QString()); } bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits) @@ -934,7 +942,7 @@ bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field } QVariant value = field->getValue(index); checkWidgetsLimits(widget, field, index, hasLimits, value, scale); - bool result = setWidgetFromVariant(widget, value, scale, field->getUnits()); + bool result = setWidgetFromVariant(widget, value, scale, field->getUnits(), field->getTypeAsString()); if (result) { return true; } else { @@ -1098,7 +1106,15 @@ QString WidgetBinding::units() const if (m_field) { return m_field->getUnits(); } - return QString(""); + return QString(); +} + +QString WidgetBinding::type() const +{ + if (m_field) { + return m_field->getTypeAsString(); + } + return QString(); } UAVObject *WidgetBinding::object() const diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h index 900aaa9a0..40ce92272 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h @@ -69,6 +69,7 @@ public: ~WidgetBinding(); QString units() const; + QString type() const; UAVObject *object() const; UAVObjectField *field() const; int index() const; @@ -223,8 +224,8 @@ private: bool setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits); - QVariant getVariantFromWidget(QWidget *widget, double scale, const QString units); - bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units); + QVariant getVariantFromWidget(QWidget *widget, double scale, const QString units, QString type); + bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units, QString type); bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale); void connectWidgetUpdatesToSlot(QWidget *widget, const char *function); From fed7fba84f963f3ee0767713e6cf00a31cbb89e0 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Thu, 8 May 2014 18:12:37 +0200 Subject: [PATCH 24/58] OP-1331 fixed alignment issues in Config Input channel list (mostly by fixing the size of items). Removed hidden channelNumber spin box. Included other minor UI cleanups (spin box text right aligned, ...). --- .../src/plugins/config/configinputwidget.cpp | 3 +- .../openpilotgcs/src/plugins/config/input.ui | 30 +- .../src/plugins/config/inputchannelform.cpp | 79 +- .../src/plugins/config/inputchannelform.h | 8 +- .../src/plugins/config/inputchannelform.ui | 1420 +++++++++-------- 5 files changed, 819 insertions(+), 721 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index a4530978b..b3568032c 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -88,7 +88,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value // to the max value ( which is smaller than the neutral value when reversed ) and the channel number // will not be set correctly. - addWidgetBinding("ManualControlSettings", "ChannelNumber", inpForm->ui->channelNumber, index); + addWidgetBinding("ManualControlSettings", "ChannelNumber", inpForm->ui->channelNumberDropdown, index); addWidgetBinding("ManualControlSettings", "ChannelGroups", inpForm->ui->channelGroup, index); addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->channelNeutral, index); addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->neutralValue, index); @@ -96,7 +96,6 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : addWidgetBinding("ManualControlSettings", "ChannelMin", inpForm->ui->channelMin, index); addWidgetBinding("ManualControlSettings", "ChannelMax", inpForm->ui->channelMax, index); - addWidget(inpForm->ui->channelNumberDropdown); addWidget(inpForm->ui->channelResponseTime); addWidget(inpForm->ui->channelRev); diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 48fee6df8..f3fa1c43b 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -116,8 +116,8 @@ 0 0 - 774 - 748 + 772 + 751 @@ -143,16 +143,16 @@ - 12 + 9 - 0 + 9 - 12 + 9 - 0 + 9 @@ -162,21 +162,21 @@ - 12 + 0 - 12 + 0 - 12 + 0 - 12 + 0 - 0 + 6 @@ -546,8 +546,8 @@ 0 0 - 774 - 748 + 724 + 497 @@ -2048,8 +2048,8 @@ Setup the flight mode channel on the RC Input tab if you have not done so alread 0 0 - 504 - 156 + 407 + 138 diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp index f6df2a3c0..adc9c7d70 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp @@ -4,30 +4,31 @@ #include "manualcontrolsettings.h" #include "gcsreceiver.h" -InputChannelForm::InputChannelForm(QWidget *parent, bool showlegend) : - ConfigTaskWidget(parent), - ui(new Ui::InputChannelForm) +InputChannelForm::InputChannelForm(QWidget *parent, bool showLegend) : + ConfigTaskWidget(parent), ui(new Ui::InputChannelForm) { ui->setupUi(this); // The first time through the loop, keep the legend. All other times, delete it. - if (!showlegend) { - layout()->removeWidget(ui->legend0); - layout()->removeWidget(ui->legend1); - layout()->removeWidget(ui->legend2); - layout()->removeWidget(ui->legend3); - layout()->removeWidget(ui->legend4); - layout()->removeWidget(ui->legend5); - layout()->removeWidget(ui->legend6); - layout()->removeWidget(ui->legend7); - delete ui->legend0; - delete ui->legend1; - delete ui->legend2; - delete ui->legend3; - delete ui->legend4; - delete ui->legend5; - delete ui->legend6; - delete ui->legend7; + if (!showLegend) { + QLayout *legendLayout = layout()->itemAt(0)->layout(); + Q_ASSERT(legendLayout); + // remove every item + while (legendLayout->count()) { + QLayoutItem *item = legendLayout->takeAt(0); + if (!item) { + continue; + } + // get widget from layout item + QWidget *widget = item->widget(); + if (widget) { + delete widget; + continue; + } + } + // and finally remove and delete the legend layout + layout()->removeItem(legendLayout); + delete legendLayout; } connect(ui->channelMin, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); @@ -36,12 +37,6 @@ InputChannelForm::InputChannelForm(QWidget *parent, bool showlegend) : connect(ui->channelGroup, SIGNAL(currentIndexChanged(int)), this, SLOT(groupUpdated())); connect(ui->channelRev, SIGNAL(toggled(bool)), this, SLOT(reversedUpdated())); - // This is awkward but since we want the UI to be a dropdown but the field is not an enum - // it breaks the UAUVObject widget relation of the task gadget. Running the data through - // a spin box fixes this - connect(ui->channelNumberDropdown, SIGNAL(currentIndexChanged(int)), this, SLOT(channelDropdownUpdated(int))); - connect(ui->channelNumber, SIGNAL(valueChanged(int)), this, SLOT(channelNumberUpdated(int))); - disableMouseWheelEvents(); } @@ -54,19 +49,6 @@ InputChannelForm::~InputChannelForm() void InputChannelForm::setName(QString &name) { ui->channelName->setText(name); - QFontMetrics metrics(ui->channelName->font()); - int width = metrics.width(name) + 5; - foreach(InputChannelForm * form, parent()->findChildren()) { - if (form == this) { - continue; - } - if (form->ui->channelName->minimumSize().width() < width) { - form->ui->channelName->setMinimumSize(width, 0); - } else { - width = form->ui->channelName->minimumSize().width(); - } - } - ui->channelName->setMinimumSize(width, 0); } /** @@ -170,23 +152,4 @@ void InputChannelForm::groupUpdated() for (int i = 0; i < count; i++) { ui->channelNumberDropdown->addItem(QString(tr("Chan %1").arg(i + 1))); } - - ui->channelNumber->setMaximum(count); - ui->channelNumber->setMinimum(0); -} - -/** - * Update the dropdown from the hidden control - */ -void InputChannelForm::channelDropdownUpdated(int newval) -{ - ui->channelNumber->setValue(newval); -} - -/** - * Update the hidden control from the dropdown - */ -void InputChannelForm::channelNumberUpdated(int newval) -{ - ui->channelNumberDropdown->setCurrentIndex(newval); } diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.h b/ground/openpilotgcs/src/plugins/config/inputchannelform.h index 91d665b40..28511bd1a 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.h @@ -1,8 +1,10 @@ #ifndef INPUTCHANNELFORM_H #define INPUTCHANNELFORM_H -#include #include "configinputwidget.h" + +#include + namespace Ui { class InputChannelForm; } @@ -11,7 +13,7 @@ class InputChannelForm : public ConfigTaskWidget { Q_OBJECT public: - explicit InputChannelForm(QWidget *parent = 0, bool showlegend = false); + explicit InputChannelForm(QWidget *parent = 0, const bool showLegend = false); ~InputChannelForm(); friend class ConfigInputWidget; void setName(QString &name); @@ -20,8 +22,6 @@ private slots: void neutralUpdated(); void reversedUpdated(); void groupUpdated(); - void channelDropdownUpdated(int); - void channelNumberUpdated(int); private: Ui::InputChannelForm *ui; diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index d07f2ae3b..5e1ee9107 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -6,14 +6,14 @@ 0 0 - 828 - 93 + 839 + 57 Form - + 0 @@ -24,566 +24,785 @@ 0 - 6 + 0 - - - - true + + + + 6 - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel neutral - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + + true + + + + 0 + 0 + + + + + 80 + 20 + + + + + -1 + 75 + false + true + + + + Channel function + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Neutral - - - Qt::AlignCenter - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - true - - - - 0 - 0 - - - - - 30 - 20 - - - - - 75 - false - true - - - - Response time - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Function + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 100 + 20 + + + + + -1 + 75 + false + true + + + + Channel type + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - RT - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 75 - 20 - - - - - 75 - false - true - - - - Channel values are inverted - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Type + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 90 + 20 + + + + + -1 + 75 + false + true + + + + Channel number + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - Reversed - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel function - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Number + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 55 + 20 + + + + + -1 + 75 + false + true + + + + Channel min + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Function - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel type - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Min + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel neutral + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Type - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel number - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Neutral + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 55 + 20 + + + + + -1 + 75 + false + true + + + + Channel max + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Number - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel min - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Max + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 75 + 20 + + + + + -1 + 75 + false + true + + + + Channel values are inverted + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - Min - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 80 - 25 - - - - TextLabel - - - - - - - - 4 - 0 - - - - - 0 - 25 - - - - - 90 - 16777215 - - - - Qt::StrongFocus - - - 7 - - - - - - - - 6 - 0 - - - - - 0 - 25 - - - - - 100 - 16777215 - - - - Qt::StrongFocus - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Channel max - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Reversed + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 45 + 20 + + + + + -1 + 75 + false + true + + + + Response time + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -margin:1px; -font:bold; - - - QFrame::StyledPanel - - - 1 - - - Max - - - Qt::AlignCenter - - +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + RT + + + Qt::AlignCenter + + + + - - - - Qt::Horizontal + + + + 6 - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 22 - - - - Qt::StrongFocus - - - Qt::Horizontal - - - - - - - true - - - - 0 - 0 - - - - - 30 - 25 - - - - Optional input filter response time. + + + + + 0 + 0 + + + + + 80 + 25 + + + + + 80 + 16777215 + + + + Text + + + + + + + + 0 + 0 + + + + + 100 + 25 + + + + + 100 + 16777215 + + + + Qt::StrongFocus + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + + 90 + 16777215 + + + + Qt::StrongFocus + + + 7 + + + + + + + + 0 + 0 + + + + + 55 + 25 + + + + + 55 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::StrongFocus + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 1000 + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + + 55 + 25 + + + + + 55 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + + + + 0 + 0 + + + + + 75 + 25 + + + + + 75 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 45 + 25 + + + + + 45 + 16777215 + + + + Optional input filter response time. Range: 0-999ms, 0 disables filter (default). @@ -591,111 +810,28 @@ Warning: this is an expert mode feature, mostly used for aerial video camera control (airframe yaw and camera gimbal accessory channels). Too high values for main controls can cause undesirable effects and even lead to crash. Use with caution. - - - false - - - true - - - QAbstractSpinBox::UpDownArrows - - - 999 - - - - - - - - 75 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - 0 - 20 - - - - - - - - - - - - - - - 0 - 25 - - - - 9999 - - - 1000 - - + + + false + + + true + + + QAbstractSpinBox::UpDownArrows + + + 999 + + + + - - - true - - - - 216 - 26 - 0 - 0 - - - - - 0 - 0 - - - - channelNumber channelGroup channelNumberDropdown - channelMin - channelNeutral - channelMax From da3d9d61fce8d0511a0b4e3e7066d1af912de556 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Thu, 8 May 2014 18:23:35 +0200 Subject: [PATCH 25/58] OP-1331 fixed alignment issues in Config Output channel list (mostly by fixing the size of items). Includes other minor UI cleanups (spin box text right aligned, ...) --- .../openpilotgcs/src/plugins/config/output.ui | 7 +- .../src/plugins/config/outputchannelform.cpp | 73 +- .../src/plugins/config/outputchannelform.ui | 1197 ++++++++++------- 3 files changed, 728 insertions(+), 549 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index aa2f892c7..3be59f710 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -122,8 +122,8 @@ 0 0 - 676 - 674 + 674 + 677 @@ -655,6 +655,9 @@ Leave at 50Hz for fixed wing. + + 6 + QLayout::SetDefaultConstraint diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index a69a88bf9..259655158 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -29,49 +29,42 @@ #include "configoutputwidget.h" OutputChannelForm::OutputChannelForm(const int index, QWidget *parent, const bool showLegend) : - ConfigTaskWidget(parent), - ui(), - m_index(index), - m_inChannelTest(false) + ConfigTaskWidget(parent), ui(), m_index(index), m_inChannelTest(false) { ui.setupUi(this); if (!showLegend) { - // Remove legend - QGridLayout *grid_layout = dynamic_cast(layout()); - Q_ASSERT(grid_layout); - for (int col = 0; col < grid_layout->columnCount(); col++) { // remove every item in first row - QLayoutItem *item = grid_layout->itemAtPosition(0, col); + QLayout *legendLayout = layout()->itemAt(0)->layout(); + Q_ASSERT(legendLayout); + // remove every item + while (legendLayout->count()) { + QLayoutItem *item = legendLayout->takeAt(0); if (!item) { continue; } // get widget from layout item - QWidget *legend_widget = item->widget(); - if (!legend_widget) { + QWidget *widget = item->widget(); + if (widget) { + delete widget; continue; } - // delete widget - grid_layout->removeWidget(legend_widget); - delete legend_widget; } + // and finally remove and delete the legend layout + layout()->removeItem(legendLayout); + delete legendLayout; } // The convention for OP is Channel 1 to Channel 10. ui.actuatorNumber->setText(QString("%1:").arg(m_index + 1)); // Register for ActuatorSettings changes: - connect(ui.actuatorMin, SIGNAL(editingFinished()), - this, SLOT(setChannelRange())); - connect(ui.actuatorMax, SIGNAL(editingFinished()), - this, SLOT(setChannelRange())); - connect(ui.actuatorRev, SIGNAL(toggled(bool)), - this, SLOT(reverseChannel(bool))); + connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); + connect(ui.actuatorMax, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); + connect(ui.actuatorRev, SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool))); // Now connect the channel out sliders to our signal to send updates in test mode - connect(ui.actuatorNeutral, SIGNAL(valueChanged(int)), - this, SLOT(sendChannelTest(int))); + connect(ui.actuatorNeutral, SIGNAL(valueChanged(int)), this, SLOT(sendChannelTest(int))); ui.actuatorLink->setChecked(false); - connect(ui.actuatorLink, SIGNAL(toggled(bool)), - this, SLOT(linkToggled(bool))); + connect(ui.actuatorLink, SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool))); disableMouseWheelEvents(); } @@ -194,19 +187,6 @@ void OutputChannelForm::neutral(int value) void OutputChannelForm::setAssignment(const QString &assignment) { ui.actuatorName->setText(assignment); - QFontMetrics metrics(ui.actuatorName->font()); - int width = metrics.width(assignment) + 1; - foreach(OutputChannelForm * form, parent()->findChildren()) { - if (form == this) { - continue; - } - if (form->ui.actuatorName->minimumSize().width() < width) { - form->ui.actuatorName->setMinimumSize(width, 0); - } else { - width = form->ui.actuatorName->minimumSize().width(); - } - } - ui.actuatorName->setMinimumSize(width, 0); } /** @@ -220,7 +200,7 @@ void OutputChannelForm::setChannelRange() { int oldMini = ui.actuatorNeutral->minimum(); -// int oldMaxi = ui.actuatorNeutral->maximum(); + // int oldMaxi = ui.actuatorNeutral->maximum(); if (ui.actuatorMin->value() < ui.actuatorMax->value()) { ui.actuatorNeutral->setRange(ui.actuatorMin->value(), ui.actuatorMax->value()); @@ -234,8 +214,9 @@ void OutputChannelForm::setChannelRange() ui.actuatorNeutral->setValue(ui.actuatorNeutral->minimum()); } -// if (ui.actuatorNeutral->value() == oldMaxi) -// ui.actuatorNeutral->setValue(ui.actuatorNeutral->maximum()); // this can be dangerous if it happens to be controlling a motor at the time! + // if (ui.actuatorNeutral->value() == oldMaxi) + // this can be dangerous if it happens to be controlling a motor at the time! + // ui.actuatorNeutral->setValue(ui.actuatorNeutral->maximum()); } /** @@ -252,8 +233,7 @@ void OutputChannelForm::reverseChannel(bool state) return; } - // Now, swap the min & max values (only on the spinboxes, the slider - // does not change! + // Now, swap the min & max values (only on the spinboxes, the slider does not change!) int temp = ui.actuatorMax->value(); ui.actuatorMax->setValue(ui.actuatorMin->value()); ui.actuatorMin->setValue(temp); @@ -286,12 +266,14 @@ void OutputChannelForm::sendChannelTest(int value) } if (ui.actuatorRev->isChecked()) { - value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); // the channel is reversed + // the channel is reversed + value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); } // update the label ui.actuatorValue->setText(QString::number(value)); - if (ui.actuatorLink->checkState() && parent()) { // the channel is linked to other channels + if (ui.actuatorLink->checkState() && parent()) { + // the channel is linked to other channels QList outputChannelForms = parent()->findChildren(); // set the linked channels of the parent widget to the same value foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { @@ -320,7 +302,8 @@ void OutputChannelForm::sendChannelTest(int value) } if (!m_inChannelTest) { - return; // we are not in Test Output mode + // we are not in Test Output mode + return; } emit channelChanged(index(), value); } diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index abe5d04dd..9e0c7fa1b 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -6,554 +6,747 @@ 0 0 - 825 - 58 + 772 + 57 Form - + + + 6 + + + 0 + - 1 + 0 + + + 0 - 1 + 0 - - 12 - - - - - - 0 - 0 - + + + + 12 - - - 45 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + Qt::LeftToRight + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Link - - - Qt::AlignCenter - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Maximum PWM value, beware of not overdriving your servo. - - - 9999 - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + # + + + Qt::AlignCenter + + + 0 + + + + + + + + 0 + 0 + + + + + 110 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Neutral (slowest for motor) - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - Qt::LeftToRight - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + Assignment + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 55 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - # - - - Qt::AlignCenter - - - 0 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + Min + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Assignment - - - Qt::AlignCenter - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Minimum PWM value, beware of not overdriving your servo. - - - 9999 - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - 9999 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + Neutral (slowest for motor) + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 55 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Max - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 20 - 25 - - - - Channel Number - - - TextLabel - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 110 - 25 - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + Max + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 75 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Reversed - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Current value of slider. - - - 0000 - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + Reversed + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 45 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; -font:bold; +font: bold 12px; margin:1px; - - - Min - - - Qt::AlignCenter - - + + + Link + + + Qt::AlignCenter + + + + - - - - - 75 - 0 - + + + + 12 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - + + + + + 0 + 0 + + + + + 20 + 25 + + + + + 20 + 16777215 + + + + Channel Number + + + 0: + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 110 + 25 + + + + + 110 + 16777215 + + + + - + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 55 + 25 + + + + + 55 + 16777215 + + + + Qt::StrongFocus + + + Minimum PWM value, beware of not overdriving your servo. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 0 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 - - - 0 - 0 - + + 0 - - Qt::StrongFocus + + 0 - - Check to invert the channel. + + 0 - - - - - - - - - - 45 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::StrongFocus + + + 9999 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 24 + 25 + + + + + 24 + 16777215 + + + + Current value of slider. + + + 0000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 55 + 25 + + + + + 55 + 16777215 + + + + Qt::StrongFocus + + + Maximum PWM value, beware of not overdriving your servo. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + QFrame::NoFrame + + + + 0 - - - 0 - 0 - + + 0 - - Qt::StrongFocus + + 0 - - Output mode + + 0 - - - - + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + Check to invert the channel. + + + + + + + + + + + 0 + 0 + + + + + 45 + 25 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + Output mode + + + + + + + actuatorMin - actuatorNeutral actuatorMax From 08dcdefc1f69be7197901d61b458fccad6c292e4 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 8 May 2014 19:48:30 +0200 Subject: [PATCH 26/58] OP-1329 set SensorConnected to false when sensorType is changed to none. --- flight/modules/Airspeed/airspeed.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/flight/modules/Airspeed/airspeed.c b/flight/modules/Airspeed/airspeed.c index 9aba9fb72..25e6821a5 100644 --- a/flight/modules/Airspeed/airspeed.c +++ b/flight/modules/Airspeed/airspeed.c @@ -157,13 +157,11 @@ static void airspeedTask(__attribute__((unused)) void *parameters) if (airspeedSettings.AirspeedSensorType != lastAirspeedSensorType) { AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); lastAirspeedSensorType = airspeedSettings.AirspeedSensorType; + if (airspeedSettings.AirspeedSensorType == AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE) { + airspeedData.SensorConnected = AIRSPEEDSENSOR_SENSORCONNECTED_FALSE; + AirspeedSensorSet(&airspeedData); + } } - if(airspeedSettings.AirspeedSensorType == AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE){ - // no need to check so often until a sensor is enabled - AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); - vTaskDelay(5000/ portTICK_RATE_MS); - continue; - } switch (airspeedSettings.AirspeedSensorType) { #if defined(PIOS_INCLUDE_MPXV) case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002: @@ -185,13 +183,17 @@ static void airspeedTask(__attribute__((unused)) void *parameters) break; #endif case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GROUNDSPEEDBASEDWINDESTIMATION: - if(!gpsAirspeedInitialized){ - gpsAirspeedInitialized = true; - gps_airspeedInitialize(); - } + if (!gpsAirspeedInitialized) { + gpsAirspeedInitialized = true; + gps_airspeedInitialize(); + } gps_airspeedGet(&airspeedData, &airspeedSettings); break; case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE: + // no need to check so often until a sensor is enabled + AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); + vTaskDelay(2000 / portTICK_RATE_MS); + continue; default: airspeedData.SensorConnected = AIRSPEEDSENSOR_SENSORCONNECTED_FALSE; break; From 3a451c97373012ee92e15b791fd4bcc2dcdcf88b Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 8 May 2014 19:58:42 +0200 Subject: [PATCH 27/58] OP-1329 Trigger a SensorType change the first time Task runs to set AirspeedSensor UAVO when sensor is None --- flight/modules/Airspeed/airspeed.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/flight/modules/Airspeed/airspeed.c b/flight/modules/Airspeed/airspeed.c index 25e6821a5..5b449f69c 100644 --- a/flight/modules/Airspeed/airspeed.c +++ b/flight/modules/Airspeed/airspeed.c @@ -60,7 +60,7 @@ static xTaskHandle taskHandle; static bool airspeedEnabled = false; static AirspeedSettingsData airspeedSettings; -static AirspeedSettingsAirspeedSensorTypeOptions lastAirspeedSensorType = 0; +static AirspeedSettingsAirspeedSensorTypeOptions lastAirspeedSensorType = -1; static int8_t airspeedADCPin = -1; @@ -119,8 +119,6 @@ int32_t AirspeedInitialize() } } - lastAirspeedSensorType = airspeedSettings.AirspeedSensorType; - AirspeedSensorInitialize(); AirspeedSettingsInitialize(); From 94beebc3d037056d52f05d4dcfbfb0b4e6d500ed Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 8 May 2014 22:26:12 +0200 Subject: [PATCH 28/58] OP-1302 Fixes for current next. Show flightmode everytime it changes when disarmed --- flight/libraries/notification.c | 90 ++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c index 4df6f71bb..9015e4dd3 100644 --- a/flight/libraries/notification.c +++ b/flight/libraries/notification.c @@ -62,9 +62,9 @@ (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000001 : \ x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000000100001 : \ x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000010000100001 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0000000000100001 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0000000000100001 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED4 ? 0b0000000000000001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED5 ? 0b0000000000100001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED6 ? 0b0000010000100001 : \ x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000010000100001 : \ x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001000100010001 : \ x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001000100010001 : \ @@ -75,9 +75,9 @@ (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000000 : \ x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000000000000 : \ x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000000000000000 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0000000000100000 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0000000000100000 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0000000000100000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED4 ? 0b0000000000000001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED5 ? 0b0000000000000001 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED6 ? 0b0000000000000001 : \ x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000010000000000 : \ x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001000100000000 : \ x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001000100000000 : \ @@ -85,31 +85,33 @@ x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0000010000000000 : 0b0000010000000000) #define BLINK_B_FM_DISARMED_PATTERN(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0001111111111111 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0001111111111111 : 0b0001111111111111) + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000110001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED4 ? 0b0000000000000011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED5 ? 0b0000000001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED6 ? 0b0000110001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000110001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0011001100110011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0011001100110011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0000110001100011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0000110001100011 : 0b0000000000000011) #define BLINK_R_FM_DISARMED_PATTERN(x) \ - (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0 : \ - x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0 : 0) + (x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED1 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED2 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED3 ? 0b0000000000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED4 ? 0b0000000000000011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED5 ? 0b0000000000000011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_STABILIZED6 ? 0b0000000000000011 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD ? 0b0000110000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE ? 0b0011001100000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_LAND ? 0b0011001100000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER ? 0b0000110000000000 : \ + x == FLIGHTSTATUS_FLIGHTMODE_POI ? 0b0000110000000000 : 0b0000110000000000) +#define BLINK_B_HEARTBEAT_PATTERN 0b0001111111111111 +#define BLINK_R_HEARTBEAT_PATTERN 0 #define BLINK_B_NOTIFY_PATTERN(x) \ (x == NOTIFY_NONE ? 0 : \ @@ -133,8 +135,8 @@ static volatile pios_notify_notification nextNotification = NOTIFY_NONE; static bool handleAlarms(uint16_t *r_pattern, uint16_t *b_pattern); #endif // PIOS_LED_ALARM static bool handleNotifications(pios_notify_notification runningNotification, uint16_t *r_pattern, uint16_t *b_pattern); -static void handleStatus(uint16_t *r_pattern, uint16_t *b_pattern); - +static void handleFlightMode(uint16_t *r_pattern, uint16_t *b_pattern); +static void handleHeartbeat(uint16_t *r_pattern, uint16_t *b_pattern); void NotificationUpdateStatus() { started = true; @@ -152,12 +154,13 @@ void NotificationOnboardLedsRun() static uint16_t r_pattern; static uint16_t b_pattern; static uint8_t cycleCount; // count the number of cycles + static uint8_t lastFlightMode = -1; + static bool forceShowFlightMode = false; static pios_notify_notification runningNotification = NOTIFY_NONE; - static enum { STATUS_NOTIFY, STATUS_ALARM, - STATUS_FLIGHTMODE, + STATUS_FLIGHTMODE, // flightMode/HeartBeat STATUS_LENGHT } status; @@ -182,6 +185,13 @@ void NotificationOnboardLedsRun() // Force a notification status status = STATUS_NOTIFY; cycleCount = 0; // instantly start a notify cycle + } else { + if (lastFlightMode != currentFlightStatus.FlightMode) { + status = STATUS_FLIGHTMODE; + lastFlightMode = currentFlightStatus.FlightMode; + cycleCount = 0; // instantly start a flightMode cycle + forceShowFlightMode = true; + } } // check if a phase has just finished @@ -189,6 +199,7 @@ void NotificationOnboardLedsRun() HEARTBEAT_LED_OFF(); ALARM_LED_OFF(); cycleCount = 0x0; + forceShowFlightMode = false; // Notification has been just shown, cleanup if (status == STATUS_NOTIFY) { runningNotification = NOTIFY_NONE; @@ -218,7 +229,11 @@ void NotificationOnboardLedsRun() // **** Handles flightmode display if (status == STATUS_FLIGHTMODE && !cycleCount) { - handleStatus(&r_pattern, &b_pattern); + if (forceShowFlightMode || currentFlightStatus.Armed != FLIGHTSTATUS_ARMED_DISARMED) { + handleFlightMode(&r_pattern, &b_pattern); + } else { + handleHeartbeat(&r_pattern, &b_pattern); + } } // led output @@ -259,7 +274,7 @@ static bool handleNotifications(pios_notify_notification runningNotification, ui return true; } -static void handleStatus(uint16_t *r_pattern, uint16_t *b_pattern) +static void handleFlightMode(uint16_t *r_pattern, uint16_t *b_pattern) { // Flash the heartbeat LED uint8_t flightmode = currentFlightStatus.FlightMode; @@ -272,3 +287,10 @@ static void handleStatus(uint16_t *r_pattern, uint16_t *b_pattern) *r_pattern = BLINK_R_FM_ARMED_PATTERN(flightmode); } } + +static void handleHeartbeat(uint16_t *r_pattern, uint16_t *b_pattern) +{ + // Flash the heartbeat LED + *b_pattern = BLINK_B_HEARTBEAT_PATTERN; + *r_pattern = BLINK_R_HEARTBEAT_PATTERN; +} From 47a891e59475e76a6e72ad24addfd778c3b0e12e Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Thu, 8 May 2014 23:05:55 +0200 Subject: [PATCH 29/58] OP-1325 fix event system warnings to be errors --- flight/modules/System/systemmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index 648e2d3a0..e9c4c2740 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -633,7 +633,7 @@ static void updateSystemAlarms() UAVObjClearStats(); EventClearStats(); if (objStats.eventCallbackErrors > 0 || objStats.eventQueueErrors > 0 || evStats.eventErrors > 0) { - AlarmsSet(SYSTEMALARMS_ALARM_EVENTSYSTEM, SYSTEMALARMS_ALARM_WARNING); + AlarmsSet(SYSTEMALARMS_ALARM_EVENTSYSTEM, SYSTEMALARMS_ALARM_ERROR); } else { AlarmsClear(SYSTEMALARMS_ALARM_EVENTSYSTEM); } From 274c6aadad197a1cc5cf3df3479576aa278741f8 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sat, 10 May 2014 20:40:14 +0200 Subject: [PATCH 30/58] OP-1331 trying new approach to address input/output channel configuration grid alignment issues. New approach is to move the individual widgets to the parent grid layout in order to have them all under the same constraints. This wip to have feedback on other OSes. --- .../src/plugins/config/configgadgetwidget.cpp | 77 +- .../src/plugins/config/configgadgetwidget.h | 3 +- .../src/plugins/config/configinputwidget.cpp | 28 +- .../src/plugins/config/configoutputwidget.cpp | 6 +- .../openpilotgcs/src/plugins/config/input.ui | 52 +- .../src/plugins/config/inputchannelform.cpp | 71 +- .../src/plugins/config/inputchannelform.h | 6 +- .../src/plugins/config/inputchannelform.ui | 1596 ++++++++--------- .../openpilotgcs/src/plugins/config/output.ui | 70 +- .../src/plugins/config/outputchannelform.cpp | 84 +- .../src/plugins/config/outputchannelform.h | 6 +- .../src/plugins/config/outputchannelform.ui | 1384 +++++++------- 12 files changed, 1726 insertions(+), 1657 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 4ae81eb08..482f42add 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -55,69 +55,67 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - ftw = new MyTabbedStackWidget(this, true, true); - ftw->setIconSize(64); + stackWidget = new MyTabbedStackWidget(this, true, true); + stackWidget->setIconSize(64); QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(ftw); + layout->addWidget(stackWidget); setLayout(layout); - // ********************* QWidget *qwd; QIcon *icon = new QIcon(); icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultHwSettingsWidget(this); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); icon = new QIcon(); icon->addFile(":/configgadget/images/vehicle_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/vehicle_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigVehicleTypeWidget(this); - ftw->insertTab(ConfigGadgetWidget::aircraft, qwd, *icon, QString("Vehicle")); + stackWidget->insertTab(ConfigGadgetWidget::aircraft, qwd, *icon, QString("Vehicle")); icon = new QIcon(); icon->addFile(":/configgadget/images/input_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/input_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigInputWidget(this); - ftw->insertTab(ConfigGadgetWidget::input, qwd, *icon, QString("Input")); + stackWidget->insertTab(ConfigGadgetWidget::input, qwd, *icon, QString("Input")); icon = new QIcon(); icon->addFile(":/configgadget/images/output_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/output_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigOutputWidget(this); - ftw->insertTab(ConfigGadgetWidget::output, qwd, *icon, QString("Output")); + stackWidget->insertTab(ConfigGadgetWidget::output, qwd, *icon, QString("Output")); icon = new QIcon(); icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultAttitudeWidget(this); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); icon = new QIcon(); icon->addFile(":/configgadget/images/stabilization_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/stabilization_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigStabilizationWidget(this); - ftw->insertTab(ConfigGadgetWidget::stabilization, qwd, *icon, QString("Stabilization")); + stackWidget->insertTab(ConfigGadgetWidget::stabilization, qwd, *icon, QString("Stabilization")); icon = new QIcon(); icon->addFile(":/configgadget/images/camstab_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/camstab_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigCameraStabilizationWidget(this); - ftw->insertTab(ConfigGadgetWidget::camerastabilization, qwd, *icon, QString("Gimbal")); + stackWidget->insertTab(ConfigGadgetWidget::camerastabilization, qwd, *icon, QString("Gimbal")); icon = new QIcon(); icon->addFile(":/configgadget/images/txpid_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/txpid_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigTxPIDWidget(this); - ftw->insertTab(ConfigGadgetWidget::txpid, qwd, *icon, QString("TxPID")); + stackWidget->insertTab(ConfigGadgetWidget::txpid, qwd, *icon, QString("TxPID")); + + stackWidget->setCurrentIndex(ConfigGadgetWidget::hardware); - ftw->setCurrentIndex(ConfigGadgetWidget::hardware); - // ********************* // Listen to autopilot connection events - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); TelemetryManager *telMngr = pm->getObject(); connect(telMngr, SIGNAL(connected()), this, SLOT(onAutopilotConnect())); @@ -129,9 +127,9 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) } help = 0; - connect(ftw, SIGNAL(currentAboutToShow(int, bool *)), this, SLOT(tabAboutToChange(int, bool *))); + connect(stackWidget, SIGNAL(currentAboutToShow(int, bool *)), this, SLOT(tabAboutToChange(int, bool *))); - // Connect to the PipXStatus object updates + // Connect to the OPLinkStatus object updates UAVObjectManager *objManager = pm->getObject(); oplinkStatusObj = dynamic_cast(objManager->getObject("OPLinkStatus")); if (oplinkStatusObj != NULL) { @@ -148,13 +146,14 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) ConfigGadgetWidget::~ConfigGadgetWidget() { - // TODO: properly delete all the tabs in ftw before exiting + // TODO: properly delete all the tabs in stackWidget before exiting + delete stackWidget } void ConfigGadgetWidget::startInputWizard() { - ftw->setCurrentIndex(ConfigGadgetWidget::input); - ConfigInputWidget *inputWidget = dynamic_cast(ftw->getWidget(ConfigGadgetWidget::input)); + stackWidget->setCurrentIndex(ConfigGadgetWidget::input); + ConfigInputWidget *inputWidget = dynamic_cast(stackWidget->getWidget(ConfigGadgetWidget::input)); Q_ASSERT(inputWidget); inputWidget->startInputWizard(); } @@ -166,24 +165,24 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event) void ConfigGadgetWidget::onAutopilotDisconnect() { - int selectedIndex = ftw->currentIndex(); + int selectedIndex = stackWidget->currentIndex(); QIcon *icon = new QIcon(); icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new DefaultAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->removeTab(ConfigGadgetWidget::sensors); + stackWidget->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); icon = new QIcon(); icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultHwSettingsWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->removeTab(ConfigGadgetWidget::hardware); + stackWidget->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); - ftw->setCurrentIndex(selectedIndex); + stackWidget->setCurrentIndex(selectedIndex); emit autopilotDisconnected(); } @@ -196,7 +195,7 @@ void ConfigGadgetWidget::onAutopilotConnect() ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectUtilManager *utilMngr = pm->getObject(); if (utilMngr) { - int selectedIndex = ftw->currentIndex(); + int selectedIndex = stackWidget->currentIndex(); int board = utilMngr->getBoardModel(); if ((board & 0xff00) == 1024) { // CopterControl family @@ -205,15 +204,15 @@ void ConfigGadgetWidget::onAutopilotConnect() icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigCCAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->removeTab(ConfigGadgetWidget::sensors); + stackWidget->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); icon = new QIcon(); icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigCCHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->removeTab(ConfigGadgetWidget::hardware); + stackWidget->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); } else if ((board & 0xff00) == 0x0900) { // Revolution family @@ -221,20 +220,20 @@ void ConfigGadgetWidget::onAutopilotConnect() icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigRevoWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + stackWidget->removeTab(ConfigGadgetWidget::sensors); + stackWidget->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); icon = new QIcon(); icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigRevoHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + stackWidget->removeTab(ConfigGadgetWidget::hardware); + stackWidget->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); } else { // Unknown board qDebug() << "Unknown board " << board; } - ftw->setCurrentIndex(selectedIndex); + stackWidget->setCurrentIndex(selectedIndex); } emit autopilotConnected(); @@ -244,7 +243,7 @@ void ConfigGadgetWidget::tabAboutToChange(int i, bool *proceed) { Q_UNUSED(i); *proceed = true; - ConfigTaskWidget *wid = qobject_cast(ftw->currentWidget()); + ConfigTaskWidget *wid = qobject_cast(stackWidget->currentWidget()); if (!wid) { return; } @@ -275,7 +274,7 @@ void ConfigGadgetWidget::updateOPLinkStatus(UAVObject *) icon->addFile(":/configgadget/images/pipx-selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigPipXtremeWidget(this); - ftw->insertTab(ConfigGadgetWidget::oplink, qwd, *icon, QString("OPLink")); + stackWidget->insertTab(ConfigGadgetWidget::oplink, qwd, *icon, QString("OPLink")); oplinkConnected = true; } } @@ -284,6 +283,6 @@ void ConfigGadgetWidget::onOPLinkDisconnect() { qDebug() << "ConfigGadgetWidget onOPLinkDisconnect"; oplinkTimeout->stop(); - ftw->removeTab(ConfigGadgetWidget::oplink); + stackWidget->removeTab(ConfigGadgetWidget::oplink); oplinkConnected = false; } diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h index 45eadd8b5..0a443b9e0 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.h @@ -65,7 +65,6 @@ signals: protected: void resizeEvent(QResizeEvent *event); - MyTabbedStackWidget *ftw; private: UAVDataObject *oplinkStatusObj; @@ -73,6 +72,8 @@ private: // A timer that timesout the connction to the OPLink. QTimer *oplinkTimeout; bool oplinkConnected; + + MyTabbedStackWidget *stackWidget; }; #endif // CONFIGGADGETWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index b3568032c..b983a1e27 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -80,24 +80,24 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : unsigned int indexRT = 0; foreach(QString name, manualSettingsObj->getField("ChannelNumber")->getElementNames()) { Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM); - InputChannelForm *inpForm = new InputChannelForm(this, index == 0); - ui->channelSettings->layout()->addWidget(inpForm); // Add the row to the UI - inpForm->setName(name); + InputChannelForm *form = new InputChannelForm(this); + form->addToGrid(ui->channelLayout); + form->setName(name); // The order of the following binding calls is important. Since the values will be populated // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value // to the max value ( which is smaller than the neutral value when reversed ) and the channel number // will not be set correctly. - addWidgetBinding("ManualControlSettings", "ChannelNumber", inpForm->ui->channelNumberDropdown, index); - addWidgetBinding("ManualControlSettings", "ChannelGroups", inpForm->ui->channelGroup, index); - addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->channelNeutral, index); - addWidgetBinding("ManualControlSettings", "ChannelNeutral", inpForm->ui->neutralValue, index); - addWidgetBinding("ManualControlSettings", "ChannelMax", inpForm->ui->channelMax, index); - addWidgetBinding("ManualControlSettings", "ChannelMin", inpForm->ui->channelMin, index); - addWidgetBinding("ManualControlSettings", "ChannelMax", inpForm->ui->channelMax, index); + addWidgetBinding("ManualControlSettings", "ChannelNumber", form->ui->channelNumber, index); + addWidgetBinding("ManualControlSettings", "ChannelGroups", form->ui->channelGroup, index); + addWidgetBinding("ManualControlSettings", "ChannelNeutral", form->ui->channelNeutral, index); + addWidgetBinding("ManualControlSettings", "ChannelNeutral", form->ui->neutralValue, index); + addWidgetBinding("ManualControlSettings", "ChannelMax", form->ui->channelMax, index); + addWidgetBinding("ManualControlSettings", "ChannelMin", form->ui->channelMin, index); + addWidgetBinding("ManualControlSettings", "ChannelMax", form->ui->channelMax, index); - addWidget(inpForm->ui->channelResponseTime); - addWidget(inpForm->ui->channelRev); + addWidget(form->ui->channelResponseTime); + addWidget(form->ui->channelRev); // Input filter response time fields supported for some channels only switch (index) { @@ -107,13 +107,13 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : case ManualControlSettings::CHANNELGROUPS_ACCESSORY0: case ManualControlSettings::CHANNELGROUPS_ACCESSORY1: case ManualControlSettings::CHANNELGROUPS_ACCESSORY2: - addWidgetBinding("ManualControlSettings", "ResponseTime", inpForm->ui->channelResponseTime, indexRT); + addWidgetBinding("ManualControlSettings", "ResponseTime", form->ui->channelResponseTime, indexRT); ++indexRT; break; case ManualControlSettings::CHANNELGROUPS_THROTTLE: case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE: case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: - inpForm->ui->channelResponseTime->setEnabled(false); + form->ui->channelResponseTime->setEnabled(false); break; default: Q_ASSERT(0); diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 9ca2ed943..5108d9b0f 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -76,10 +76,12 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren // NOTE: we have channel indices from 0 to 9, but the convention for OP is Channel 1 to Channel 10. // Register for ActuatorSettings changes: for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) { - OutputChannelForm *form = new OutputChannelForm(i, this, i == 0); + OutputChannelForm *form = new OutputChannelForm(i, this); + form->addToGrid(ui->channelLayout); + connect(ui->channelOutTest, SIGNAL(toggled(bool)), form, SLOT(enableChannelTest(bool))); connect(form, SIGNAL(channelChanged(int, int)), this, SLOT(sendChannelTest(int, int))); - ui->channelLayout->addWidget(form); + addWidget(form->ui.actuatorMin); addWidget(form->ui.actuatorNeutral); addWidget(form->ui.actuatorMax); diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index f3fa1c43b..b53d7ba6d 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -174,9 +174,9 @@ 0 - - - 6 + + + 12 @@ -198,7 +198,7 @@ - + Qt::Horizontal @@ -211,14 +211,14 @@ - + Roll/Pitch/Yaw stick deadband - + Stick deadband in percents of full range (0-10), zero to disable @@ -234,22 +234,6 @@ - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 12 - 20 - - - - @@ -260,7 +244,7 @@ 20 - 40 + 10 @@ -369,6 +353,12 @@ + + + 0 + 0 + + 210 @@ -413,6 +403,12 @@ true + + + 0 + 0 + + 210 @@ -546,8 +542,8 @@ 0 0 - 724 - 497 + 772 + 751 @@ -2048,8 +2044,8 @@ Setup the flight mode channel on the RC Input tab if you have not done so alread 0 0 - 407 - 138 + 772 + 751 @@ -2238,7 +2234,7 @@ Set to 0 to disable (recommended for soaring fixed wings). - + :/core/images/helpicon.svg:/core/images/helpicon.svg diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp index adc9c7d70..788b96d2f 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp @@ -4,13 +4,31 @@ #include "manualcontrolsettings.h" #include "gcsreceiver.h" -InputChannelForm::InputChannelForm(QWidget *parent, bool showLegend) : - ConfigTaskWidget(parent), ui(new Ui::InputChannelForm) +InputChannelForm::InputChannelForm(QWidget *parent) : ConfigTaskWidget(parent), ui(new Ui::InputChannelForm) { ui->setupUi(this); + connect(ui->channelMin, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); + connect(ui->channelMax, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); + connect(ui->neutralValue, SIGNAL(valueChanged(int)), this, SLOT(neutralUpdated())); + connect(ui->channelGroup, SIGNAL(currentIndexChanged(int)), this, SLOT(groupUpdated())); + connect(ui->channelRev, SIGNAL(toggled(bool)), this, SLOT(reversedUpdated())); + + disableMouseWheelEvents(); +} + +InputChannelForm::~InputChannelForm() +{ + delete ui; +} + +void InputChannelForm::addToGrid(QGridLayout *gridLayout) +{ + // if we are the first row to be inserted the show the legend + bool showLegend = (gridLayout->rowCount() == 1); + // The first time through the loop, keep the legend. All other times, delete it. - if (!showLegend) { + if (false && !showLegend) { QLayout *legendLayout = layout()->itemAt(0)->layout(); Q_ASSERT(legendLayout); // remove every item @@ -31,19 +49,40 @@ InputChannelForm::InputChannelForm(QWidget *parent, bool showLegend) : delete legendLayout; } - connect(ui->channelMin, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); - connect(ui->channelMax, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); - connect(ui->neutralValue, SIGNAL(valueChanged(int)), this, SLOT(neutralUpdated())); - connect(ui->channelGroup, SIGNAL(currentIndexChanged(int)), this, SLOT(groupUpdated())); - connect(ui->channelRev, SIGNAL(toggled(bool)), this, SLOT(reversedUpdated())); + QGridLayout *srcLayout = dynamic_cast(layout()); + Q_ASSERT(srcLayout); - disableMouseWheelEvents(); -} + if (showLegend) { + Q_ASSERT(srcLayout); + int row = gridLayout->rowCount(); + for(int col = 0; col < srcLayout->columnCount(); col++) { + QLayoutItem *item = srcLayout->itemAtPosition(0, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + gridLayout->addWidget(widget, row, col); + continue; + } + } + } + int row = gridLayout->rowCount(); + for(int col = 0; col < srcLayout->columnCount(); col++) { + QLayoutItem *item = srcLayout->itemAtPosition(1, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + gridLayout->addWidget(widget, row, col); + continue; + } + } -InputChannelForm::~InputChannelForm() -{ - delete ui; + // + setVisible(false); } void InputChannelForm::setName(QString &name) @@ -118,8 +157,8 @@ void InputChannelForm::reversedUpdated() */ void InputChannelForm::groupUpdated() { - ui->channelNumberDropdown->clear(); - ui->channelNumberDropdown->addItem("Disabled"); + ui->channelNumber->clear(); + ui->channelNumber->addItem("Disabled"); quint8 count = 0; @@ -150,6 +189,6 @@ void InputChannelForm::groupUpdated() } for (int i = 0; i < count; i++) { - ui->channelNumberDropdown->addItem(QString(tr("Chan %1").arg(i + 1))); + ui->channelNumber->addItem(QString(tr("Chan %1").arg(i + 1))); } } diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.h b/ground/openpilotgcs/src/plugins/config/inputchannelform.h index 28511bd1a..ad17d0963 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.h @@ -13,10 +13,14 @@ class InputChannelForm : public ConfigTaskWidget { Q_OBJECT public: - explicit InputChannelForm(QWidget *parent = 0, const bool showLegend = false); + explicit InputChannelForm(QWidget *parent = 0); ~InputChannelForm(); + friend class ConfigInputWidget; + void setName(QString &name); + void addToGrid(QGridLayout *gridLayout); + private slots: void minMaxUpdated(); void neutralUpdated(); diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index 5e1ee9107..b9052fece 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -6,14 +6,14 @@ 0 0 - 839 - 57 + 859 + 51 Form - + 0 @@ -26,783 +26,34 @@ 0 - - - - 6 + + 12 + + + + + true - - - - true - - - - 0 - 0 - - - - - 80 - 20 - - - - - -1 - 75 - false - true - - - - Channel function - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Function - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 100 - 20 - - - - - -1 - 75 - false - true - - - - Channel type - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Type - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 90 - 20 - - - - - -1 - 75 - false - true - - - - Channel number - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Number - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 55 - 20 - - - - - -1 - 75 - false - true - - - - Channel min - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Min - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - -1 - 75 - false - true - - - - Channel neutral - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Neutral - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - true - - - - 0 - 0 - - - - - 55 - 20 - - - - - -1 - 75 - false - true - - - - Channel max - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - 1 - - - Max - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 75 - 20 - - - - - -1 - 75 - false - true - - - - Channel values are inverted - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - 1 - - - Reversed - - - Qt::AlignCenter - - - - - - - true - - - - 0 - 0 - - - - - 45 - 20 - - - - - -1 - 75 - false - true - - - - Response time - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - 1 - - - RT - - - Qt::AlignCenter - - - - - - - - - 6 + + + 0 + 0 + - - - - - 0 - 0 - - - - - 80 - 25 - - - - - 80 - 16777215 - - - - Text - - - - - - - - 0 - 0 - - - - - 100 - 25 - - - - - 100 - 16777215 - - - - Qt::StrongFocus - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - - 90 - 16777215 - - - - Qt::StrongFocus - - - 7 - - - - - - - - 0 - 0 - - - - - 55 - 25 - - - - - 55 - 16777215 - - - - Qt::StrongFocus - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 50 - 0 - - - - Qt::StrongFocus - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 9999 - - - 1000 - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - - 55 - 25 - - - - - 55 - 16777215 - - - - Qt::StrongFocus - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - - 0 - 0 - - - - - 75 - 25 - - - - - 75 - 16777215 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 0 - 20 - - - - - - - - - - - - - - true - - - - 0 - 0 - - - - - 45 - 25 - - - - - 45 - 16777215 - - - - Optional input filter response time. + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Optional input filter response time. Range: 0-999ms, 0 disables filter (default). @@ -810,29 +61,778 @@ Warning: this is an expert mode feature, mostly used for aerial video camera control (airframe yaw and camera gimbal accessory channels). Too high values for main controls can cause undesirable effects and even lead to crash. Use with caution. - - - false - - - true - - - QAbstractSpinBox::UpDownArrows - - - 999 - - - - + + + false + + + true + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 999 + + + + + + + + 0 + 0 + + + + + 80 + 0 + + + + + 16777215 + 16777215 + + + + Text + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + 7 + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 80 + 20 + + + + + -1 + 75 + false + true + + + + Channel function + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Function + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 75 + 20 + + + + + -1 + 75 + false + true + + + + Channel values are inverted + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Reversed + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 50 + 20 + + + + + -1 + 75 + false + true + + + + Response time + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + RT + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 50 + 20 + + + + + -1 + 75 + false + true + + + + Channel max + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + 1 + + + Max + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel neutral + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Neutral + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 50 + 20 + + + + + -1 + 75 + false + true + + + + Channel min + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Min + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 90 + 20 + + + + + -1 + 75 + false + true + + + + Channel number + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Number + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + + 100 + 20 + + + + + -1 + 75 + false + true + + + + Channel type + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Type + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::StrongFocus + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 60 + 16777215 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 1000 + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + + - - channelGroup - channelNumberDropdown - diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index 3be59f710..575b03e58 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -654,44 +654,46 @@ Leave at 50Hz for fixed wing. - - - 6 - - - QLayout::SetDefaultConstraint + + + 12 - - - - - - 519 - 20 - - - - Motors spin at neutral output when armed and throttle below zero (be careful) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + 0 + 0 + + + + + 519 + 20 + + + + Motors spin at neutral output when armed and throttle below zero (be careful) + + diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index 259655158..b5d9c2358 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -28,30 +28,10 @@ #include "outputchannelform.h" #include "configoutputwidget.h" -OutputChannelForm::OutputChannelForm(const int index, QWidget *parent, const bool showLegend) : +OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : ConfigTaskWidget(parent), ui(), m_index(index), m_inChannelTest(false) { ui.setupUi(this); - if (!showLegend) { - QLayout *legendLayout = layout()->itemAt(0)->layout(); - Q_ASSERT(legendLayout); - // remove every item - while (legendLayout->count()) { - QLayoutItem *item = legendLayout->takeAt(0); - if (!item) { - continue; - } - // get widget from layout item - QWidget *widget = item->widget(); - if (widget) { - delete widget; - continue; - } - } - // and finally remove and delete the legend layout - layout()->removeItem(legendLayout); - delete legendLayout; - } // The convention for OP is Channel 1 to Channel 10. ui.actuatorNumber->setText(QString("%1:").arg(m_index + 1)); @@ -74,6 +54,68 @@ OutputChannelForm::~OutputChannelForm() // Do nothing } +void OutputChannelForm::addToGrid(QGridLayout *gridLayout) +{ + // if we are the first row to be inserted the show the legend + bool showLegend = (gridLayout->rowCount() == 1); + + if (false && !showLegend) { + QLayout *legendLayout = layout()->itemAt(0)->layout(); + Q_ASSERT(legendLayout); + // remove every item + while (legendLayout->count()) { + QLayoutItem *item = legendLayout->takeAt(0); + if (!item) { + continue; + } + // get widget from layout item + QWidget *widget = item->widget(); + if (widget) { + delete widget; + continue; + } + } + // and finally remove and delete the legend layout + layout()->removeItem(legendLayout); + delete legendLayout; + } + + QGridLayout *srcLayout = dynamic_cast(layout()); + Q_ASSERT(srcLayout); + + if (showLegend) { + Q_ASSERT(srcLayout); + int row = gridLayout->rowCount(); + for(int col = 0; col < srcLayout->columnCount(); col++) { + QLayoutItem *item = srcLayout->itemAtPosition(0, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + gridLayout->addWidget(widget, row, col); + continue; + } + } + } + + int row = gridLayout->rowCount(); + for(int col = 0; col < srcLayout->columnCount(); col++) { + QLayoutItem *item = srcLayout->itemAtPosition(1, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + gridLayout->addWidget(widget, row, col); + continue; + } + } + + // + setVisible(false); +} + /** * Restrict UI to protect users from accidental misuse. */ diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index a537f55e7..c854548b2 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -35,12 +35,14 @@ class OutputChannelForm : public ConfigTaskWidget { Q_OBJECT public: - explicit OutputChannelForm(const int index, QWidget *parent = NULL, const bool showLegend = false); + explicit OutputChannelForm(const int index, QWidget *parent = NULL); ~OutputChannelForm(); + friend class ConfigOutputWidget; void setAssignment(const QString &assignment); int index() const; + void addToGrid(QGridLayout *gridLayout); public slots: void max(int maximum); @@ -57,7 +59,7 @@ signals: private: Ui::outputChannelForm ui; - /// Channel index + // Channel index int m_index; bool m_inChannelTest; diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index 9e0c7fa1b..c5a542622 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -7,16 +7,13 @@ 0 0 772 - 57 + 51 Form - - - 6 - + 0 @@ -29,726 +26,711 @@ 0 - - - - 12 + + 12 + + + + + + 0 + 0 + - - - - - 0 - 0 - - - - - 20 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - Qt::LeftToRight - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); + + + 110 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); color: rgb(255, 255, 255); border-radius: 5; font: bold 12px; margin:1px; - - - # - - - Qt::AlignCenter - - - 0 - - - - - - - - 0 - 0 - - - - - 110 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Assignment - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 55 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Min - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Neutral (slowest for motor) - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 55 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Max - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 75 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Reversed - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 45 - 20 - - - - - 16777215 - 16777215 - - - - - -1 - 75 - false - true - - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - Link - - - Qt::AlignCenter - - - - + + + Assignment + + + Qt::AlignCenter + + - - - - 12 + + + + + 0 + 0 + - - - - - 0 - 0 - - - - - 20 - 25 - - - - - 20 - 16777215 - - - - Channel Number - - - 0: - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 110 - 25 - - - - - 110 - 16777215 - - - - - - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 55 - 25 - - - - - 55 - 16777215 - - - - Qt::StrongFocus - - - Minimum PWM value, beware of not overdriving your servo. - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 9999 - - - 0 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 + + + 50 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Min + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Neutral (slowest for motor) + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + Qt::LeftToRight + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + # + + + Qt::AlignCenter + + + 0 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Minimum PWM value, beware of not overdriving your servo. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + 0 + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + Channel Number + + + 0: + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Max + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 75 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Reversed + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 45 + 20 + + + + + 16777215 + 16777215 + + + + + -1 + 75 + false + true + + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + Link + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 110 + 0 + + + + + 16777215 + 16777215 + + + + - + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Maximum PWM value, beware of not overdriving your servo. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + 0 + 0 + - - 0 + + + 50 + 0 + - - 0 + + Qt::StrongFocus - - 0 + + 9999 - - - - - 0 - 0 - - - - - 50 - 0 - - - - Qt::StrongFocus - - - 9999 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 24 - 25 - - - - - 24 - 16777215 - - - - Current value of slider. - - - 0000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 0 - 0 - - - - - 55 - 25 - - - - - 55 - 16777215 - - - - Qt::StrongFocus - - - Maximum PWM value, beware of not overdriving your servo. - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 9999 - - - - - - - - 0 - 0 - - - - - 75 - 0 - - - - QFrame::NoFrame - - - - 0 + + Qt::Horizontal - - 0 + + + + + + + 0 + 0 + - - 0 + + + 20 + 0 + - - 0 + + + 16777215 + 16777215 + - - 0 + + Current value of slider. - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::StrongFocus - - - Check to invert the channel. - - - - - - - - - - - 0 - 0 - - - - - 45 - 25 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 + + 0000 - - 0 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 0 + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + QFrame::NoFrame + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + - - 0 + + + 0 + 0 + - - 0 + + Qt::StrongFocus - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::StrongFocus - - - Output mode - - - - - - - + + Check to invert the channel. + + + + + + + + + + + 0 + 0 + + + + + 45 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + Output mode + + + + + - - actuatorMin - actuatorMax - From 711c5ea79dfbbc04bc308fd2a95951b7b3f906d7 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 11 May 2014 10:43:24 +0200 Subject: [PATCH 31/58] OP-1312 Fixes the flicker issue in Revo. Raised the Transfer complete irq priotity to prevent delays stopping the timer. --- flight/targets/boards/discoveryf4bare/board_hw_defs.c | 2 +- flight/targets/boards/revolution/board_hw_defs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flight/targets/boards/discoveryf4bare/board_hw_defs.c b/flight/targets/boards/discoveryf4bare/board_hw_defs.c index 73ca21c81..4583fe6b4 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1864,7 +1864,7 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, .NVIC_IRQChannelSubPriority = 0, .NVIC_IRQChannelCmd = ENABLE, }, diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 13a202091..98fce19c7 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -2085,7 +2085,7 @@ const struct pios_ws2811_cfg pios_ws2811_cfg = { .flags = (DMA_IT_TCIF1), .init = { .NVIC_IRQChannel = DMA2_Stream1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, .NVIC_IRQChannelSubPriority = 0, .NVIC_IRQChannelCmd = ENABLE, }, From 7155805b79d2b27ae528fee5700f2c1d6d0eb012 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 11 May 2014 11:33:11 +0200 Subject: [PATCH 32/58] OP-1329 Move gps airspeed initialization checks under "sensor changed" test --- flight/modules/Airspeed/airspeed.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/flight/modules/Airspeed/airspeed.c b/flight/modules/Airspeed/airspeed.c index 5b449f69c..5cbe8e162 100644 --- a/flight/modules/Airspeed/airspeed.c +++ b/flight/modules/Airspeed/airspeed.c @@ -155,9 +155,19 @@ static void airspeedTask(__attribute__((unused)) void *parameters) if (airspeedSettings.AirspeedSensorType != lastAirspeedSensorType) { AlarmsSet(SYSTEMALARMS_ALARM_AIRSPEED, SYSTEMALARMS_ALARM_DEFAULT); lastAirspeedSensorType = airspeedSettings.AirspeedSensorType; - if (airspeedSettings.AirspeedSensorType == AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE) { + switch (airspeedSettings.AirspeedSensorType) { + case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE: + // AirspeedSensor will not be updated until a different sensor is selected + // set the disconencted satus now airspeedData.SensorConnected = AIRSPEEDSENSOR_SENSORCONNECTED_FALSE; AirspeedSensorSet(&airspeedData); + break; + case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GROUNDSPEEDBASEDWINDESTIMATION: + if (!gpsAirspeedInitialized) { + gpsAirspeedInitialized = true; + gps_airspeedInitialize(); + } + break; } } switch (airspeedSettings.AirspeedSensorType) { @@ -181,10 +191,6 @@ static void airspeedTask(__attribute__((unused)) void *parameters) break; #endif case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GROUNDSPEEDBASEDWINDESTIMATION: - if (!gpsAirspeedInitialized) { - gpsAirspeedInitialized = true; - gps_airspeedInitialize(); - } gps_airspeedGet(&airspeedData, &airspeedSettings); break; case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_NONE: From 45efaffcf19277ed883f995583688a8fdf23723d Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 11 May 2014 11:38:08 +0200 Subject: [PATCH 33/58] OP-1330 fix namings/uncrustify --- flight/modules/GPS/GPS.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index 402c1d55e..b20aba170 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -63,24 +63,24 @@ static float GravityAccel(float latitude, float longitude, float altitude); // **************** // Private constants -#define GPS_TIMEOUT_MS 500 +#define GPS_TIMEOUT_MS 500 // delay from detecting HomeLocation.Set == False before setting new homelocation // this prevent that a save with homelocation.Set = false triggered by gps ends saving // the new location with Set = true. -#define HOMELOCATIONSETDELAY 5000 +#define GPS_HOMELOCATION_SET_DELAY 5000 #ifdef PIOS_GPS_SETS_HOMELOCATION // Unfortunately need a good size stack for the WMM calculation - #define STACK_SIZE_BYTES 1024 + #define STACK_SIZE_BYTES 1024 #else #if defined(PIOS_GPS_MINIMAL) - #define STACK_SIZE_BYTES 500 + #define STACK_SIZE_BYTES 500 #else - #define STACK_SIZE_BYTES 650 + #define STACK_SIZE_BYTES 650 #endif // PIOS_GPS_MINIMAL #endif // PIOS_GPS_SETS_HOMELOCATION -#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) // **************** // Private variables @@ -263,13 +263,13 @@ static void gpsTask(__attribute__((unused)) void *parameters) HomeLocationGet(&home); if (home.Set == HOMELOCATION_SET_FALSE) { - if(homelocationSetDelay == 0){ - homelocationSetDelay = xTaskGetTickCount(); - } - if(xTaskGetTickCount() - homelocationSetDelay > HOMELOCATIONSETDELAY){ - setHomeLocation(&gpspositionsensor); - homelocationSetDelay = 0; - } + if (homelocationSetDelay == 0) { + homelocationSetDelay = xTaskGetTickCount(); + } + if (xTaskGetTickCount() - homelocationSetDelay > GPS_HOMELOCATION_SET_DELAY) { + setHomeLocation(&gpspositionsensor); + homelocationSetDelay = 0; + } } #endif } else if ((gpspositionsensor.Status == GPSPOSITIONSENSOR_STATUS_FIX3D) && From 953b7cc2a7039834f6118ca310e7c0a6124fef37 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 11 May 2014 12:37:20 +0200 Subject: [PATCH 34/58] OP-1330 Fix a compilation issue with CC/CC3D --- flight/modules/GPS/GPS.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index b20aba170..0a2dbc3b0 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -202,7 +202,9 @@ static void gpsTask(__attribute__((unused)) void *parameters) { portTickType xDelay = 100 / portTICK_RATE_MS; uint32_t timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS; +#ifdef PIOS_GPS_SETS_HOMELOCATION portTickType homelocationSetDelay = 0; +#endif GPSPositionSensorData gpspositionsensor; GPSSettingsData gpsSettings; From 40ed1fc570c9885479646ee4335996aa20893347 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 14:20:31 +0200 Subject: [PATCH 35/58] OP-1174 fixed GCS telemetry build dependency issue --- ground/openpilotgcs/src/plugins/plugins.pro | 5 +++-- ground/openpilotgcs/src/plugins/telemetry/telemetry.pro | 9 +++------ .../src/plugins/telemetry/telemetry_dependencies.pri | 4 ++-- ground/openpilotgcs/src/plugins/uploader/uploader.pro | 5 ++--- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro index c09d5567d..2019d848d 100644 --- a/ground/openpilotgcs/src/plugins/plugins.pro +++ b/ground/openpilotgcs/src/plugins/plugins.pro @@ -52,8 +52,9 @@ plugin_uavtalk.depends += plugin_coreplugin # Telemetry plugin SUBDIRS += plugin_telemetry plugin_telemetry.subdir = telemetry +plugin_telemetry.depends = plugin_coreplugin +plugin_telemetry.depends += plugin_uavobjectutil plugin_telemetry.depends += plugin_uavtalk -plugin_telemetry.depends += plugin_coreplugin # OPMap UAVGadget plugin_opmap.subdir = opmap @@ -98,9 +99,9 @@ macx:contains(QT_VERSION, ^4\\.8\\.0): CONFIG += disable_notify_plugin plugin_uploader.subdir = uploader plugin_uploader.depends = plugin_coreplugin plugin_uploader.depends += plugin_uavobjects +plugin_uploader.depends += plugin_uavobjectutil plugin_uploader.depends += plugin_uavtalk plugin_uploader.depends += plugin_opHID -plugin_uploader.depends += plugin_uavobjectutil SUBDIRS += plugin_uploader # Dial gadget diff --git a/ground/openpilotgcs/src/plugins/telemetry/telemetry.pro b/ground/openpilotgcs/src/plugins/telemetry/telemetry.pro index 42335df16..a1d8a8ad9 100644 --- a/ground/openpilotgcs/src/plugins/telemetry/telemetry.pro +++ b/ground/openpilotgcs/src/plugins/telemetry/telemetry.pro @@ -1,12 +1,11 @@ TEMPLATE = lib TARGET = Telemetry +DEFINES += TELEMETRY_LIBRARY QT += svg -include(../../openpilotgcsplugin.pri) -include(../../plugins/coreplugin/coreplugin.pri) -include(../../libs/version_info/version_info.pri) include(telemetry_dependencies.pri) +include(../../libs/version_info/version_info.pri) HEADERS += telemetry_global.h \ telemetryplugin.h \ @@ -23,8 +22,6 @@ SOURCES += telemetryplugin.cpp \ monitorgadgetfactory.cpp \ monitorgadgetoptionspage.cpp -DEFINES += TELEMETRY_LIBRARY +OTHER_FILES += Telemetry.pluginspec RESOURCES += telemetry.qrc - -OTHER_FILES += Telemetry.pluginspec diff --git a/ground/openpilotgcs/src/plugins/telemetry/telemetry_dependencies.pri b/ground/openpilotgcs/src/plugins/telemetry/telemetry_dependencies.pri index 3ee3a36e1..702d40aee 100644 --- a/ground/openpilotgcs/src/plugins/telemetry/telemetry_dependencies.pri +++ b/ground/openpilotgcs/src/plugins/telemetry/telemetry_dependencies.pri @@ -1,4 +1,4 @@ -include(../../plugins/uavobjects/uavobjects.pri) +include(../../openpilotgcsplugin.pri) +include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/uavobjectutil/uavobjectutil.pri) include(../../plugins/uavtalk/uavtalk.pri) - diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader.pro b/ground/openpilotgcs/src/plugins/uploader/uploader.pro index 20e358c8b..9dbdcc56b 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploader.pro +++ b/ground/openpilotgcs/src/plugins/uploader/uploader.pro @@ -46,15 +46,14 @@ SOURCES += uploadergadget.cpp \ SSP/qsspt.cpp \ runningdevicewidget.cpp -OTHER_FILES += Uploader.pluginspec \ +OTHER_FILES += Uploader.pluginspec FORMS += \ uploader.ui \ devicewidget.ui \ runningdevicewidget.ui -RESOURCES += \ - uploader.qrc +RESOURCES += uploader.qrc exists( ../../../../../build/openpilotgcs-synthetics/opfw_resource.qrc ) { RESOURCES += ../../../../../build/openpilotgcs-synthetics/opfw_resource.qrc From 6c65b13c2b6d9ca865a55e4db3d73fd6ccc9ed00 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 15:41:00 +0200 Subject: [PATCH 36/58] OP-1340 fixed regression introduced with OP-1233 : when packaging target opfw_resources was not executed before target openpilotgcs anymore --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 008d1176c..2f17cfc69 100644 --- a/Makefile +++ b/Makefile @@ -747,7 +747,7 @@ ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),) # Packaged GCS should depend on opfw_resource ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),) - $(eval openpilotgcs: $(OPFW_RESOURCE)) + $(eval openpilotgcs_qmake: $(OPFW_RESOURCE)) endif # Clean the build directory if clean_package is requested From 9012f0aa89ba9d477f945d5833311741309e65a6 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 16:20:07 +0200 Subject: [PATCH 37/58] OP-1331 commented out useless GCS logging --- .../src/plugins/coreplugin/mainwindow.cpp | 2 +- .../src/plugins/uavobjects/uavobjectfield.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp index 12b89cd46..79f725c55 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp @@ -270,7 +270,7 @@ void MainWindow::extensionsInitialized() // We'll use qApp macro to get the QApplication pointer // and set the style sheet application wide. - qDebug() << "Setting application style sheet to:" << style; + //qDebug() << "Setting application style sheet to:" << style; qApp->setStyleSheet(style); qs->endGroup(); diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp index 235448a57..0fad83714 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp @@ -199,14 +199,14 @@ void UAVObjectField::limitsInitialize(const QString &limits) elementLimits.insert(index, limitList); ++index; } - foreach(QList limitList, elementLimits) { - foreach(LimitStruct limit, limitList) { - qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); - foreach(QVariant var, limit.values) { - qDebug() << "value" << var; - } - } - } + // foreach(QList limitList, elementLimits) { + // foreach(LimitStruct limit, limitList) { + // qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); + // foreach(QVariant var, limit.values) { + // qDebug() << "value" << var; + // } + // } + // } } bool UAVObjectField::isWithinLimits(QVariant var, quint32 index, int board) { From fcc16367eb8ca5c201ed152254625b470847d6f9 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 16:30:31 +0200 Subject: [PATCH 38/58] OP-1331 fixed compilation error in configgadgetwidet introduced with last commit --- ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 482f42add..b95baf502 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -147,7 +147,7 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent) ConfigGadgetWidget::~ConfigGadgetWidget() { // TODO: properly delete all the tabs in stackWidget before exiting - delete stackWidget + delete stackWidget; } void ConfigGadgetWidget::startInputWizard() From 048ca0787f0b87c0bbdb80cfb31e38f19e173e6d Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 17:32:04 +0200 Subject: [PATCH 39/58] OP-1343 GCS Config - Input Channel Response Time was not saved + Made visible only for relevant channels. --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index b983a1e27..05ba198f2 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -96,7 +96,6 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : addWidgetBinding("ManualControlSettings", "ChannelMin", form->ui->channelMin, index); addWidgetBinding("ManualControlSettings", "ChannelMax", form->ui->channelMax, index); - addWidget(form->ui->channelResponseTime); addWidget(form->ui->channelRev); // Input filter response time fields supported for some channels only @@ -113,7 +112,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : case ManualControlSettings::CHANNELGROUPS_THROTTLE: case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE: case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: - form->ui->channelResponseTime->setEnabled(false); + form->ui->channelResponseTime->setVisible(false); break; default: Q_ASSERT(0); From b6a297c40fbdd67d9648f3aa76996665463cc09b Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 17:42:44 +0200 Subject: [PATCH 40/58] OP-1159 Removed "Rev" checkboxes on input tab for channels on which it doesn't have an effect --- .../openpilotgcs/src/plugins/config/configinputwidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 05ba198f2..491e36ab8 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -98,6 +98,13 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : addWidget(form->ui->channelRev); + // Reversing supported for some channels only + bool reversable = ((index == ManualControlSettings::CHANNELGROUPS_THROTTLE) || + (index == ManualControlSettings::CHANNELGROUPS_ROLL) || + (index == ManualControlSettings::CHANNELGROUPS_PITCH) || + (index == ManualControlSettings::CHANNELGROUPS_YAW)); + form->ui->channelRev->setVisible(reversable); + // Input filter response time fields supported for some channels only switch (index) { case ManualControlSettings::CHANNELGROUPS_ROLL: From 9cf24a97310cc17e492962a5e27b36dcbddc2c63 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 17:46:37 +0200 Subject: [PATCH 41/58] OP-1331 minor tweaks to output channel form --- ground/openpilotgcs/src/plugins/config/outputchannelform.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index c5a542622..da55a432b 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -554,7 +554,7 @@ margin:1px; - + 0 0 @@ -586,7 +586,7 @@ margin:1px; - 20 + 25 0 From 88100a72c2b222d86b9d9da35f43d4ddbd775d07 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 18:48:39 +0200 Subject: [PATCH 42/58] OP-1331 OP-1335 revisited GComboBox to integer binding (less hacky now ;) ) --- .../src/plugins/uavobjects/uavobjectfield.cpp | 88 +++++-------------- .../src/plugins/uavobjects/uavobjectfield.h | 1 + .../uavobjectwidgetutils/configtaskwidget.cpp | 73 ++++++++------- .../uavobjectwidgetutils/configtaskwidget.h | 8 +- 4 files changed, 66 insertions(+), 104 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp index 0fad83714..fb88f9808 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp @@ -199,14 +199,14 @@ void UAVObjectField::limitsInitialize(const QString &limits) elementLimits.insert(index, limitList); ++index; } - // foreach(QList limitList, elementLimits) { - // foreach(LimitStruct limit, limitList) { - // qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); - // foreach(QVariant var, limit.values) { - // qDebug() << "value" << var; - // } - // } - // } + // foreach(QList limitList, elementLimits) { + // foreach(LimitStruct limit, limitList) { + // qDebug() << "Limit type" << limit.type << "for board" << limit.board << "for field" << getName(); + // foreach(QVariant var, limit.values) { + // qDebug() << "value" << var; + // } + // } + // } } bool UAVObjectField::isWithinLimits(QVariant var, quint32 index, int board) { @@ -811,44 +811,31 @@ bool UAVObjectField::isNumeric() { switch (type) { case INT8: - return true; - - break; case INT16: - return true; - - break; case INT32: - return true; - - break; case UINT8: - return true; - - break; case UINT16: - return true; - - break; case UINT32: - return true; - - break; case FLOAT32: return true; break; - case ENUM: + default: return false; + } +} - break; - case BITFIELD: +bool UAVObjectField::isInteger() +{ + switch (type) { + case INT8: + case INT16: + case INT32: + case UINT8: + case UINT16: + case UINT32: return true; - break; - case STRING: - return false; - break; default: return false; @@ -858,42 +845,7 @@ bool UAVObjectField::isNumeric() bool UAVObjectField::isText() { switch (type) { - case INT8: - return false; - - break; - case INT16: - return false; - - break; - case INT32: - return false; - - break; - case UINT8: - return false; - - break; - case UINT16: - return false; - - break; - case UINT32: - return false; - - break; - case FLOAT32: - return false; - - break; case ENUM: - return true; - - break; - case BITFIELD: - return false; - - break; case STRING: return true; diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h index 141fa6af7..778096729 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.h @@ -71,6 +71,7 @@ public: quint32 getDataOffset(); quint32 getNumBytes(); bool isNumeric(); + bool isInteger(); bool isText(); QString toString(); void toXML(QXmlStreamWriter *xmlWriter); diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index bc0a52f6d..19c9ff8fb 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -182,9 +182,9 @@ void ConfigTaskWidget::setWidgetBindingObjectEnabled(QString objectName, bool en binding->setIsEnabled(enabled); if (enabled) { if (binding->value().isValid() && !binding->value().isNull()) { - setWidgetFromVariant(binding->widget(), binding->value(), binding->scale()); + setWidgetFromVariant(binding->widget(), binding->value(), binding); } else { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } } @@ -289,7 +289,7 @@ void ConfigTaskWidget::populateWidgets() foreach(WidgetBinding * binding, m_widgetBindingsPerObject) { if (binding->isEnabled() && binding->object() != NULL && binding->field() != NULL && binding->widget() != NULL) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } setDirty(dirtyBack); @@ -305,7 +305,7 @@ void ConfigTaskWidget::refreshWidgetsValues(UAVObject *obj) emit refreshWidgetsValuesRequested(); foreach(WidgetBinding * binding, m_widgetBindingsPerObject.values(obj)) { if (binding->isEnabled() && binding->field() != NULL && binding->widget() != NULL) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } setDirty(dirtyBack); @@ -385,13 +385,15 @@ void ConfigTaskWidget::forceShadowUpdates() if (!binding->isEnabled()) { continue; } - QVariant widgetValue = getVariantFromWidget(binding->widget(), binding->scale(), binding->units(), binding->type()); + QVariant widgetValue = getVariantFromWidget(binding->widget(), binding); foreach(ShadowWidgetBinding * shadow, binding->shadows()) { disconnectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); checkWidgetsLimits(shadow->widget(), binding->field(), binding->index(), shadow->isLimited(), widgetValue, shadow->scale()); - setWidgetFromVariant(shadow->widget(), widgetValue, shadow->scale()); + + WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); + setWidgetFromVariant(shadow->widget(), widgetValue, &tmpBinding); emit widgetContentsChanged(shadow->widget()); connectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); @@ -410,19 +412,18 @@ void ConfigTaskWidget::widgetsContentsChanged() foreach(WidgetBinding * binding, m_widgetBindingsPerWidget.values(emitter)) { if (binding && binding->isEnabled()) { if (binding->widget() == emitter) { - scale = binding->scale(); checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), - getVariantFromWidget(emitter, scale, binding->units(), binding->type()), scale); + getVariantFromWidget(emitter, binding), binding->scale()); } else { foreach(ShadowWidgetBinding * shadow, binding->shadows()) { if (shadow->widget() == emitter) { - scale = shadow->scale(); - checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), - getVariantFromWidget(emitter, scale, binding->units(), binding->type()), scale); + WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); + QVariant value = getVariantFromWidget(emitter, &tmpBinding); + checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), value, scale); } } } - value = getVariantFromWidget(emitter, scale, binding->units(), binding->type()); + value = getVariantFromWidget(emitter, binding); binding->setValue(value); if (binding->widget() != emitter) { @@ -430,7 +431,7 @@ void ConfigTaskWidget::widgetsContentsChanged() checkWidgetsLimits(binding->widget(), binding->field(), binding->index(), binding->isLimited(), value, binding->scale()); - setWidgetFromVariant(binding->widget(), value, binding->scale()); + setWidgetFromVariant(binding->widget(), value, binding); emit widgetContentsChanged(binding->widget()); connectWidgetUpdatesToSlot(binding->widget(), SLOT(widgetsContentsChanged())); @@ -441,7 +442,8 @@ void ConfigTaskWidget::widgetsContentsChanged() checkWidgetsLimits(shadow->widget(), binding->field(), binding->index(), shadow->isLimited(), value, shadow->scale()); - setWidgetFromVariant(shadow->widget(), value, shadow->scale()); + WidgetBinding tmp(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); + setWidgetFromVariant(shadow->widget(), value, &tmp); emit widgetContentsChanged(shadow->widget()); connectWidgetUpdatesToSlot(shadow->widget(), SLOT(widgetsContentsChanged())); @@ -736,7 +738,7 @@ void ConfigTaskWidget::defaultButtonClicked() continue; } UAVDataObject *temp = ((UAVDataObject *)binding->object())->dirtyClone(); - setWidgetFromField(binding->widget(), temp->getField(binding->field()->getName()), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), temp->getField(binding->field()->getName()), binding); } } @@ -779,7 +781,7 @@ void ConfigTaskWidget::reloadButtonClicked() if (m_realtimeUpdateTimer->isActive()) { binding->object()->requestUpdate(); if (binding->widget()) { - setWidgetFromField(binding->widget(), binding->field(), binding->index(), binding->scale(), binding->isLimited()); + setWidgetFromField(binding->widget(), binding->field(), binding); } } m_realtimeUpdateTimer->stop(); @@ -851,10 +853,12 @@ void ConfigTaskWidget::disconnectWidgetUpdatesToSlot(QWidget *widget, const char } } -QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, QString units, QString type) +QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, WidgetBinding *binding) { + double scale = binding->scale(); + if (QComboBox * cb = qobject_cast(widget)) { - if (type.startsWith("int") || type.startsWith("uint")) { + if (binding->isInteger()) { return cb->currentIndex(); } return (QString)cb->currentText(); @@ -868,7 +872,7 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, Q return (QString)(cb->isChecked() ? "TRUE" : "FALSE"); } else if (QLineEdit * cb = qobject_cast(widget)) { QString value = (QString)cb->displayText(); - if (units == "hex") { + if (binding->units() == "hex") { bool ok; return value.toUInt(&ok, 16); } else { @@ -879,11 +883,13 @@ QVariant ConfigTaskWidget::getVariantFromWidget(QWidget *widget, double scale, Q } } -bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units, QString type) +bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, WidgetBinding *binding) { + double scale = binding->scale(); + if (QComboBox * cb = qobject_cast(widget)) { bool ok = true; - if (type.startsWith("int") || type.startsWith("uint")) { + if (binding->isInteger()) { cb->setCurrentIndex(value.toInt(&ok)); } else { cb->setCurrentIndex(cb->findText(value.toString())); @@ -911,7 +917,7 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou return true; } else if (QLineEdit * cb = qobject_cast(widget)) { if ((scale == 0) || (scale == 1)) { - if (units == "hex") { + if (binding->units() == "hex") { cb->setText(QString::number(value.toUInt(), 16).toUpper()); } else { cb->setText(value.toString()); @@ -925,24 +931,19 @@ bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, dou } } -bool ConfigTaskWidget::setWidgetFromVariant(QWidget *widget, QVariant value, double scale) -{ - return setWidgetFromVariant(widget, value, scale, QString(), QString()); -} - -bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits) +bool ConfigTaskWidget::setWidgetFromField(QWidget *widget, UAVObjectField *field, WidgetBinding *binding) { if (!widget || !field) { return false; } if (QComboBox * cb = qobject_cast(widget)) { if (cb->count() == 0) { - loadWidgetLimits(cb, field, index, hasLimits, scale); + loadWidgetLimits(cb, field, binding->index(), binding->isLimited(), binding->scale()); } } - QVariant value = field->getValue(index); - checkWidgetsLimits(widget, field, index, hasLimits, value, scale); - bool result = setWidgetFromVariant(widget, value, scale, field->getUnits(), field->getTypeAsString()); + QVariant value = field->getValue(binding->index()); + checkWidgetsLimits(widget, field, binding->index(), binding->isLimited(), value, binding->scale()); + bool result = setWidgetFromVariant(widget, value, binding); if (result) { return true; } else { @@ -1117,6 +1118,14 @@ QString WidgetBinding::type() const return QString(); } +bool WidgetBinding::isInteger() const +{ + if (m_field) { + return m_field->isInteger(); + } + return false; +} + UAVObject *WidgetBinding::object() const { return m_object; diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h index 40ce92272..048c4fc98 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.h @@ -70,6 +70,7 @@ public: QString units() const; QString type() const; + bool isInteger() const; UAVObject *object() const; UAVObjectField *field() const; int index() const; @@ -222,11 +223,10 @@ private: QString m_outOfLimitsStyle; QTimer *m_realtimeUpdateTimer; - bool setWidgetFromField(QWidget *widget, UAVObjectField *field, int index, double scale, bool hasLimits); + bool setWidgetFromField(QWidget *widget, UAVObjectField *field, WidgetBinding *binding); - QVariant getVariantFromWidget(QWidget *widget, double scale, const QString units, QString type); - bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale, QString units, QString type); - bool setWidgetFromVariant(QWidget *widget, QVariant value, double scale); + QVariant getVariantFromWidget(QWidget *widget, WidgetBinding *binding); + bool setWidgetFromVariant(QWidget *widget, QVariant value, WidgetBinding *binding); void connectWidgetUpdatesToSlot(QWidget *widget, const char *function); void disconnectWidgetUpdatesToSlot(QWidget *widget, const char *function); From 7affc8d12fa219726191a41d984b89637d1eabbf Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 18:53:49 +0200 Subject: [PATCH 43/58] OP-1331 OP-1335 BITFIELD was removed by mistake from UAVObjectField::isNumeric() (self review) --- ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp index fb88f9808..1ab86536a 100644 --- a/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjects/uavobjectfield.cpp @@ -817,6 +817,7 @@ bool UAVObjectField::isNumeric() case UINT16: case UINT32: case FLOAT32: + case BITFIELD: return true; break; From 8bbb56337b0e95c9a22037ee69cde1d3fe6c9c74 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 11 May 2014 18:57:06 +0200 Subject: [PATCH 44/58] OP-1312 keep pulse timings low to have more margin to handle bus contentions and irq response time. --- flight/pios/inc/pios_ws2811.h | 5 +++++ flight/pios/stm32f4xx/pios_ws2811.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h index 65f84a59a..cb05070ee 100644 --- a/flight/pios/inc/pios_ws2811.h +++ b/flight/pios/inc/pios_ws2811.h @@ -44,6 +44,11 @@ #define PIOS_WS2811_PERIPHERALDATASIZE DMA_PeripheralDataSize_HalfWord #define PIOS_WS2811_TIM_PERIOD 20 +// Following times are keept on the lower side to accounts +// for bus contentions and irq response time +#define PIOS_WS2811_T0_HIGH_PERIOD 25 // .35us +/- 150nS +#define PIOS_WS2811_T1_HIGH_PERIOD 60 // .70us +/- 150nS + #define PIOS_WS2811_DMA_CH1_CONFIG(channel) \ { \ .DMA_BufferSize = PIOS_WS2811_BUFFER_SIZE, \ diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index b3933ce26..6faf1f7c6 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -215,10 +215,10 @@ void setupTimer() }; // (duty in ticks) / (period in ticks) * 1.25uS (period in S) = 0.40 uS - oc.TIM_Pulse = 40 * PIOS_WS2811_TIM_PERIOD / 125; + oc.TIM_Pulse = PIOS_WS2811_T0_HIGH_PERIOD * PIOS_WS2811_TIM_PERIOD / 125; genericTIM_OCxInit(pios_ws2811_cfg->timer, &oc, pios_ws2811_cfg->timerCh1); // (duty in ticks) / (period in ticks) * 1.25uS (period in S) = 0.80 uS - oc.TIM_Pulse = 80 * PIOS_WS2811_TIM_PERIOD / 125; + oc.TIM_Pulse = PIOS_WS2811_T1_HIGH_PERIOD * PIOS_WS2811_TIM_PERIOD / 125; genericTIM_OCxInit(pios_ws2811_cfg->timer, &oc, pios_ws2811_cfg->timerCh2); } @@ -337,7 +337,7 @@ void PIOS_WS2811_Update() void PIOS_WS2811_DMA_irq_handler() { - TIM_Cmd(pios_ws2811_cfg->timer, DISABLE); + pios_ws2811_cfg->timer->CR1 &= (uint16_t) ~TIM_CR1_CEN; DMA_ClearFlag(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->irq.flags); } From 38b0617596cb2bcc877ba72ea8a22033e5ae1b0e Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 11 May 2014 22:08:35 +0200 Subject: [PATCH 45/58] OP-1331 uncrustified --- ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp index 79f725c55..81817c5d1 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/mainwindow.cpp @@ -270,7 +270,7 @@ void MainWindow::extensionsInitialized() // We'll use qApp macro to get the QApplication pointer // and set the style sheet application wide. - //qDebug() << "Setting application style sheet to:" << style; + // qDebug() << "Setting application style sheet to:" << style; qApp->setStyleSheet(style); qs->endGroup(); From 6804e5fe8e678939eb84952ee0e1faf9f8209f75 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Mon, 12 May 2014 22:30:50 +0200 Subject: [PATCH 46/58] OP-1331 factored common code between InputChannelForm and OutputChannelForm into new abstract class ChannelForm --- .../src/plugins/config/channelform.cpp | 73 +++++++++++ .../src/plugins/config/channelform.h | 36 ++++++ .../src/plugins/config/config.pro | 19 ++- .../src/plugins/config/configinputwidget.cpp | 10 +- .../src/plugins/config/configoutputwidget.cpp | 16 +-- .../src/plugins/config/configoutputwidget.h | 10 +- .../src/plugins/config/inputchannelform.cpp | 70 ++-------- .../src/plugins/config/inputchannelform.h | 9 +- .../src/plugins/config/outputchannelform.cpp | 121 ++++++------------ .../src/plugins/config/outputchannelform.h | 44 ++----- 10 files changed, 203 insertions(+), 205 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/config/channelform.cpp create mode 100644 ground/openpilotgcs/src/plugins/config/channelform.h diff --git a/ground/openpilotgcs/src/plugins/config/channelform.cpp b/ground/openpilotgcs/src/plugins/config/channelform.cpp new file mode 100644 index 000000000..a15a5f713 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/channelform.cpp @@ -0,0 +1,73 @@ +#include "channelform.h" + +#include + + +ChannelForm::ChannelForm(const int index, QWidget *parent) : ConfigTaskWidget(parent), m_index(index) +{} + +ChannelForm::~ChannelForm() +{} + +int ChannelForm::index() const +{ + return m_index; +} + +void ChannelForm::moveTo(QGridLayout &dstLayout) +{ + QGridLayout *srcLayout = dynamic_cast(layout()); + + Q_ASSERT(srcLayout); + + // if we are the first row to be inserted then show the legend + bool showLegend = (dstLayout.rowCount() == 1); + + if (showLegend) { + // move legend row to target grid layout + moveRow(0, *srcLayout, dstLayout); + } else { + removeRow(0, *srcLayout); + } + + // move field row to target grid layout + moveRow(1, *srcLayout, dstLayout); + + // this form is now empty so hide it + setVisible(false); +} + +void ChannelForm::moveRow(int row, QGridLayout &srcLayout, QGridLayout &dstLayout) +{ + int dstRow = dstLayout.rowCount(); + + for (int col = 0; col < srcLayout.columnCount(); col++) { + QLayoutItem *item = srcLayout.itemAtPosition(row, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + dstLayout.addWidget(widget, dstRow, col); + continue; + } + // TODO handle item of type QLayout + } +} + +void ChannelForm::removeRow(int row, QGridLayout &layout) +{ + for (int col = 0; col < layout.columnCount(); col++) { + QLayoutItem *item = layout.itemAtPosition(row, col); + if (!item) { + continue; + } + QWidget *widget = item->widget(); + if (widget) { + layout.removeWidget(widget); + delete widget; + continue; + } + // TODO handle item of type QLayout + } +} diff --git a/ground/openpilotgcs/src/plugins/config/channelform.h b/ground/openpilotgcs/src/plugins/config/channelform.h new file mode 100644 index 000000000..6c62a2f4b --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/channelform.h @@ -0,0 +1,36 @@ +#ifndef CHANNELFORM_H +#define CHANNELFORM_H + +#include "configtaskwidget.h" + +#include + +namespace Ui { +class ChannelForm; +} + +class QGridLayout; + +class ChannelForm : public ConfigTaskWidget { + Q_OBJECT + +public: + explicit ChannelForm(const int index, QWidget *parent = 0); + ~ChannelForm(); + + int index() const; + + virtual QString name() = 0; + virtual void setName(const QString &name) = 0; + + void moveTo(QGridLayout &dstLayout); + +private: + // Channel index + int m_index; + + static void moveRow(int row, QGridLayout &srcLayout, QGridLayout &dstLayout); + static void removeRow(int row, QGridLayout &layout); +}; + +#endif // CHANNELFORM_H diff --git a/ground/openpilotgcs/src/plugins/config/config.pro b/ground/openpilotgcs/src/plugins/config/config.pro index 06b56a8f1..747557191 100644 --- a/ground/openpilotgcs/src/plugins/config/config.pro +++ b/ground/openpilotgcs/src/plugins/config/config.pro @@ -1,18 +1,19 @@ TEMPLATE = lib TARGET = Config DEFINES += CONFIG_LIBRARY -QT += svg -QT += opengl -QT += qml quick + +QT += svg opengl qml quick include(config_dependencies.pri) INCLUDEPATH += ../../libs/eigen -OTHER_FILES += Config.pluginspec \ +OTHER_FILES += \ + Config.pluginspec \ calibration/WizardStepIndicator.qml -HEADERS += configplugin.h \ +HEADERS += \ + configplugin.h \ configgadgetwidget.h \ configgadgetfactory.h \ configgadget.h \ @@ -27,6 +28,7 @@ HEADERS += configplugin.h \ assertions.h \ defaultattitudewidget.h \ defaulthwsettingswidget.h \ + channelform.h \ inputchannelform.h \ configcamerastabilizationwidget.h \ configtxpidwidget.h \ @@ -53,7 +55,8 @@ HEADERS += configplugin.h \ calibration/thermal/settingshandlingtransitions.h \ calibration/thermal/compensationcalculationtransition.h -SOURCES += configplugin.cpp \ +SOURCES += \ + configplugin.cpp \ configgadgetwidget.cpp \ configgadgetfactory.cpp \ configgadget.cpp \ @@ -67,6 +70,7 @@ SOURCES += configplugin.cpp \ configpipxtremewidget.cpp \ defaultattitudewidget.cpp \ defaulthwsettingswidget.cpp \ + channelform.cpp \ inputchannelform.cpp \ configcamerastabilizationwidget.cpp \ configrevowidget.cpp \ @@ -88,7 +92,8 @@ SOURCES += configplugin.cpp \ calibration/thermal/thermalcalibrationhelper.cpp \ calibration/thermal/thermalcalibrationmodel.cpp -FORMS += airframe.ui \ +FORMS += \ + airframe.ui \ airframe_ccpm.ui \ airframe_fixedwing.ui \ airframe_ground.ui \ diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 491e36ab8..709eabf8f 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -80,9 +80,9 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : unsigned int indexRT = 0; foreach(QString name, manualSettingsObj->getField("ChannelNumber")->getElementNames()) { Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM); - InputChannelForm *form = new InputChannelForm(this); - form->addToGrid(ui->channelLayout); + InputChannelForm *form = new InputChannelForm(index, this); form->setName(name); + form->moveTo(*(ui->channelLayout)); // The order of the following binding calls is important. Since the values will be populated // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value @@ -100,9 +100,9 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : // Reversing supported for some channels only bool reversable = ((index == ManualControlSettings::CHANNELGROUPS_THROTTLE) || - (index == ManualControlSettings::CHANNELGROUPS_ROLL) || - (index == ManualControlSettings::CHANNELGROUPS_PITCH) || - (index == ManualControlSettings::CHANNELGROUPS_YAW)); + (index == ManualControlSettings::CHANNELGROUPS_ROLL) || + (index == ManualControlSettings::CHANNELGROUPS_PITCH) || + (index == ManualControlSettings::CHANNELGROUPS_YAW)); form->ui->channelRev->setVisible(reversable); // Input filter response time fields supported for some channels only diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp index 5108d9b0f..ba9618eea 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.cpp @@ -77,7 +77,7 @@ ConfigOutputWidget::ConfigOutputWidget(QWidget *parent) : ConfigTaskWidget(paren // Register for ActuatorSettings changes: for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) { OutputChannelForm *form = new OutputChannelForm(i, this); - form->addToGrid(ui->channelLayout); + form->moveTo(*(ui->channelLayout)); connect(ui->channelOutTest, SIGNAL(toggled(bool)), form, SLOT(enableChannelTest(bool))); connect(form, SIGNAL(channelChanged(int, int)), this, SLOT(sendChannelTest(int, int))); @@ -196,7 +196,7 @@ OutputChannelForm *ConfigOutputWidget::getOutputChannelForm(const int index) con /** * Set the label for a channel output assignement */ -void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str) +void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString &str) { // FIXME: use signal/ slot approach UAVObjectField *field = obj->getField(str); @@ -206,7 +206,7 @@ void ConfigOutputWidget::assignOutputChannel(UAVDataObject *obj, QString str) OutputChannelForm *outputChannelForm = getOutputChannelForm(index); if (outputChannelForm) { - outputChannelForm->setAssignment(str); + outputChannelForm->setName(str); } } @@ -256,15 +256,15 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) // Initialize output forms QList outputChannelForms = findChildren(); foreach(OutputChannelForm * outputChannelForm, outputChannelForms) { - outputChannelForm->setAssignment(ChannelDesc[outputChannelForm->index()]); + outputChannelForm->setName(ChannelDesc[outputChannelForm->index()]); // init min,max,neutral int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; - outputChannelForm->minmax(minValue, maxValue); + outputChannelForm->setRange(minValue, maxValue); int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; - outputChannelForm->neutral(neutral); + outputChannelForm->setNeutral(neutral); } // Get the SpinWhileArmed setting @@ -351,10 +351,10 @@ void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj) int minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()]; int maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()]; - outputChannelForm->minmax(minValue, maxValue); + outputChannelForm->setRange(minValue, maxValue); int neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()]; - outputChannelForm->neutral(neutral); + outputChannelForm->setNeutral(neutral); } setDirty(dirty); diff --git a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h index 1cabfb5a2..fda2922c6 100644 --- a/ground/openpilotgcs/src/plugins/config/configoutputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configoutputwidget.h @@ -47,6 +47,8 @@ public: ConfigOutputWidget(QWidget *parent = 0); ~ConfigOutputWidget(); +protected: + void enableControls(bool enable); private: Ui_OutputWidget *ui; @@ -55,14 +57,14 @@ private: void updateChannelInSlider(QSlider *slider, QLabel *min, QLabel *max, QCheckBox *rev, int value); - void assignChannel(UAVDataObject *obj, QString str); - void assignOutputChannel(UAVDataObject *obj, QString str); + void assignOutputChannel(UAVDataObject *obj, QString &str); OutputChannelForm *getOutputChannelForm(const int index) const; int mccDataRate; UAVObject::Metadata accInitialData; bool wasItMe; + private slots: void stopTests(); void disableIfNotMe(UAVObject *obj); @@ -71,8 +73,6 @@ private slots: void runChannelTests(bool state); void sendChannelTest(int index, int value); void openHelp(); -protected: - void enableControls(bool enable); }; -#endif // ifndef CONFIGOUTPUTWIDGET_H +#endif // CONFIGOUTPUTWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp index 788b96d2f..8d5ff8c7f 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.cpp @@ -4,7 +4,8 @@ #include "manualcontrolsettings.h" #include "gcsreceiver.h" -InputChannelForm::InputChannelForm(QWidget *parent) : ConfigTaskWidget(parent), ui(new Ui::InputChannelForm) +InputChannelForm::InputChannelForm(const int index, QWidget *parent) : + ChannelForm(index, parent), ui(new Ui::InputChannelForm) { ui->setupUi(this); @@ -22,70 +23,15 @@ InputChannelForm::~InputChannelForm() delete ui; } -void InputChannelForm::addToGrid(QGridLayout *gridLayout) +QString InputChannelForm::name() { - // if we are the first row to be inserted the show the legend - bool showLegend = (gridLayout->rowCount() == 1); - - // The first time through the loop, keep the legend. All other times, delete it. - if (false && !showLegend) { - QLayout *legendLayout = layout()->itemAt(0)->layout(); - Q_ASSERT(legendLayout); - // remove every item - while (legendLayout->count()) { - QLayoutItem *item = legendLayout->takeAt(0); - if (!item) { - continue; - } - // get widget from layout item - QWidget *widget = item->widget(); - if (widget) { - delete widget; - continue; - } - } - // and finally remove and delete the legend layout - layout()->removeItem(legendLayout); - delete legendLayout; - } - - QGridLayout *srcLayout = dynamic_cast(layout()); - Q_ASSERT(srcLayout); - - if (showLegend) { - Q_ASSERT(srcLayout); - int row = gridLayout->rowCount(); - for(int col = 0; col < srcLayout->columnCount(); col++) { - QLayoutItem *item = srcLayout->itemAtPosition(0, col); - if (!item) { - continue; - } - QWidget *widget = item->widget(); - if (widget) { - gridLayout->addWidget(widget, row, col); - continue; - } - } - } - - int row = gridLayout->rowCount(); - for(int col = 0; col < srcLayout->columnCount(); col++) { - QLayoutItem *item = srcLayout->itemAtPosition(1, col); - if (!item) { - continue; - } - QWidget *widget = item->widget(); - if (widget) { - gridLayout->addWidget(widget, row, col); - continue; - } - } - - // - setVisible(false); + return ui->channelName->text(); } -void InputChannelForm::setName(QString &name) +/** + * Set the channel assignment label. + */ +void InputChannelForm::setName(const QString &name) { ui->channelName->setText(name); } diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.h b/ground/openpilotgcs/src/plugins/config/inputchannelform.h index ad17d0963..f48bcbd0a 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.h @@ -1,6 +1,7 @@ #ifndef INPUTCHANNELFORM_H #define INPUTCHANNELFORM_H +#include "channelform.h" #include "configinputwidget.h" #include @@ -9,17 +10,17 @@ namespace Ui { class InputChannelForm; } -class InputChannelForm : public ConfigTaskWidget { +class InputChannelForm : public ChannelForm { Q_OBJECT public: - explicit InputChannelForm(QWidget *parent = 0); + explicit InputChannelForm(const int index, QWidget *parent = NULL); ~InputChannelForm(); friend class ConfigInputWidget; - void setName(QString &name); - void addToGrid(QGridLayout *gridLayout); + virtual QString name(); + virtual void setName(const QString &name); private slots: void minMaxUpdated(); diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index b5d9c2358..da8514855 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -26,15 +26,14 @@ */ #include "outputchannelform.h" -#include "configoutputwidget.h" OutputChannelForm::OutputChannelForm(const int index, QWidget *parent) : - ConfigTaskWidget(parent), ui(), m_index(index), m_inChannelTest(false) + ChannelForm(index, parent), ui(), m_inChannelTest(false) { ui.setupUi(this); // The convention for OP is Channel 1 to Channel 10. - ui.actuatorNumber->setText(QString("%1:").arg(m_index + 1)); + ui.actuatorNumber->setText(QString("%1:").arg(index + 1)); // Register for ActuatorSettings changes: connect(ui.actuatorMin, SIGNAL(editingFinished()), this, SLOT(setChannelRange())); @@ -54,66 +53,17 @@ OutputChannelForm::~OutputChannelForm() // Do nothing } -void OutputChannelForm::addToGrid(QGridLayout *gridLayout) +QString OutputChannelForm::name() { - // if we are the first row to be inserted the show the legend - bool showLegend = (gridLayout->rowCount() == 1); + return ui.actuatorName->text(); +} - if (false && !showLegend) { - QLayout *legendLayout = layout()->itemAt(0)->layout(); - Q_ASSERT(legendLayout); - // remove every item - while (legendLayout->count()) { - QLayoutItem *item = legendLayout->takeAt(0); - if (!item) { - continue; - } - // get widget from layout item - QWidget *widget = item->widget(); - if (widget) { - delete widget; - continue; - } - } - // and finally remove and delete the legend layout - layout()->removeItem(legendLayout); - delete legendLayout; - } - - QGridLayout *srcLayout = dynamic_cast(layout()); - Q_ASSERT(srcLayout); - - if (showLegend) { - Q_ASSERT(srcLayout); - int row = gridLayout->rowCount(); - for(int col = 0; col < srcLayout->columnCount(); col++) { - QLayoutItem *item = srcLayout->itemAtPosition(0, col); - if (!item) { - continue; - } - QWidget *widget = item->widget(); - if (widget) { - gridLayout->addWidget(widget, row, col); - continue; - } - } - } - - int row = gridLayout->rowCount(); - for(int col = 0; col < srcLayout->columnCount(); col++) { - QLayoutItem *item = srcLayout->itemAtPosition(1, col); - if (!item) { - continue; - } - QWidget *widget = item->widget(); - if (widget) { - gridLayout->addWidget(widget, row, col); - continue; - } - } - - // - setVisible(false); +/** + * Set the channel assignment label. + */ +void OutputChannelForm::setName(const QString &name) +{ + ui.actuatorName->setText(name); } /** @@ -184,26 +134,49 @@ void OutputChannelForm::linkToggled(bool state) } } +int OutputChannelForm::max() const +{ + return ui.actuatorMax->value(); +} + /** * Set maximal channel value. */ -void OutputChannelForm::max(int maximum) +void OutputChannelForm::setMax(int maximum) { - minmax(ui.actuatorMin->value(), maximum); + setRange(ui.actuatorMin->value(), maximum); +} + +int OutputChannelForm::min() const +{ + return ui.actuatorMin->value(); } /** * Set minimal channel value. */ -void OutputChannelForm::min(int minimum) +void OutputChannelForm::setMin(int minimum) { - minmax(minimum, ui.actuatorMax->value()); + setRange(minimum, ui.actuatorMax->value()); +} + +int OutputChannelForm::neutral() const +{ + return ui.actuatorNeutral->value(); +} + +/** + * Set neutral of channel. + */ +void OutputChannelForm::setNeutral(int value) +{ + ui.actuatorNeutral->setValue(value); } /** * Set minimal and maximal channel value. */ -void OutputChannelForm::minmax(int minimum, int maximum) +void OutputChannelForm::setRange(int minimum, int maximum) { ui.actuatorMin->setValue(minimum); ui.actuatorMax->setValue(maximum); @@ -215,22 +188,6 @@ void OutputChannelForm::minmax(int minimum, int maximum) } } -/** - * Set neutral of channel. - */ -void OutputChannelForm::neutral(int value) -{ - ui.actuatorNeutral->setValue(value); -} - -/** - * Set the channel assignment label. - */ -void OutputChannelForm::setAssignment(const QString &assignment) -{ - ui.actuatorName->setText(assignment); -} - /** * Sets the minimum/maximum value of the channel output sliders. * Have to do it here because setMinimum is not a slot. diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.h b/ground/openpilotgcs/src/plugins/config/outputchannelform.h index c854548b2..78d008115 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.h +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.h @@ -27,11 +27,13 @@ #ifndef OUTPUTCHANNELFORM_H #define OUTPUTCHANNELFORM_H -#include +#include "channelform.h" +#include "configoutputwidget.h" #include "ui_outputchannelform.h" -#include "configtaskwidget.h" -class OutputChannelForm : public ConfigTaskWidget { +#include + +class OutputChannelForm : public ChannelForm { Q_OBJECT public: @@ -40,18 +42,17 @@ public: friend class ConfigOutputWidget; - void setAssignment(const QString &assignment); - int index() const; - void addToGrid(QGridLayout *gridLayout); + virtual QString name(); + virtual void setName(const QString &name); public slots: - void max(int maximum); - int max() const; - void min(int minimum); int min() const; - void minmax(int minimum, int maximum); - void neutral(int value); + void setMin(int minimum); + int max() const; + void setMax(int maximum); int neutral() const; + void setNeutral(int value); + void setRange(int minimum, int maximum); void enableChannelTest(bool state); signals: @@ -59,8 +60,6 @@ signals: private: Ui::outputChannelForm ui; - // Channel index - int m_index; bool m_inChannelTest; private slots: @@ -70,23 +69,4 @@ private slots: void setChannelRange(); }; -inline int OutputChannelForm::index() const -{ - return m_index; -} - -inline int OutputChannelForm::max() const -{ - return ui.actuatorMax->value(); -} - -inline int OutputChannelForm::min() const -{ - return ui.actuatorMin->value(); -} - -inline int OutputChannelForm::neutral() const -{ - return ui.actuatorNeutral->value(); -} #endif // OUTPUTCHANNELFORM_H From e9f14544f9e06220232cd8832f23107d7fe171de Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Mon, 12 May 2014 22:42:01 +0200 Subject: [PATCH 47/58] OP-1346 GCS was not allowing setting the ResponseTime for the Collective input channel. Worse GCS would then shift the values (Accessory0 would go to Collective, Accessory1 to Accessory0, Accessory2 to Accessory1 and Accessory2 would always be zero) --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 709eabf8f..1f5402a06 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -110,6 +110,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : case ManualControlSettings::CHANNELGROUPS_ROLL: case ManualControlSettings::CHANNELGROUPS_PITCH: case ManualControlSettings::CHANNELGROUPS_YAW: + case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: case ManualControlSettings::CHANNELGROUPS_ACCESSORY0: case ManualControlSettings::CHANNELGROUPS_ACCESSORY1: case ManualControlSettings::CHANNELGROUPS_ACCESSORY2: @@ -118,7 +119,6 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : break; case ManualControlSettings::CHANNELGROUPS_THROTTLE: case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE: - case ManualControlSettings::CHANNELGROUPS_COLLECTIVE: form->ui->channelResponseTime->setVisible(false); break; default: From 47976312c29720a02e391d7554e1b6daff30f5d7 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 12 May 2014 22:56:28 +0200 Subject: [PATCH 48/58] OP-1330 reset Home Set delay timer if Set==true --- flight/modules/GPS/GPS.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index 0a2dbc3b0..bdbad1f69 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -202,6 +202,7 @@ static void gpsTask(__attribute__((unused)) void *parameters) { portTickType xDelay = 100 / portTICK_RATE_MS; uint32_t timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS; + #ifdef PIOS_GPS_SETS_HOMELOCATION portTickType homelocationSetDelay = 0; #endif @@ -272,6 +273,8 @@ static void gpsTask(__attribute__((unused)) void *parameters) setHomeLocation(&gpspositionsensor); homelocationSetDelay = 0; } + } else { + homelocationSetDelay = 0; } #endif } else if ((gpspositionsensor.Status == GPSPOSITIONSENSOR_STATUS_FIX3D) && From 513ba37746ee254920bd703b299f5aef36d352bc Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Tue, 13 May 2014 22:04:01 +0200 Subject: [PATCH 49/58] OP-1348 Congig gadget would briefly flash next widget when replacing the currently selected widget --- .../src/libs/utils/mytabbedstackwidget.cpp | 22 +++++++- .../src/libs/utils/mytabbedstackwidget.h | 1 + .../src/plugins/config/configgadgetwidget.cpp | 50 ++++--------------- 3 files changed, 33 insertions(+), 40 deletions(-) diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp index 2626ca47b..ed1bd75ae 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp @@ -83,12 +83,31 @@ MyTabbedStackWidget::MyTabbedStackWidget(QWidget *parent, bool isVertical, bool void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon &icon, const QString &label) { tab->setContentsMargins(0, 0, 0, 0); - m_stackWidget->insertWidget(index, tab); + + // create and insert item QListWidgetItem *item = new QListWidgetItem(icon, label); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); item->setToolTip(label); m_listWidget->insertItem(index, item); + + // insert widget + m_stackWidget->insertWidget(index, tab); +} + +void MyTabbedStackWidget::replaceTab(int index, QWidget *tab) +{ + QWidget *wid = m_stackWidget->widget(index); + + // insert new widget + m_stackWidget->insertWidget(index, tab); + if (index == currentIndex()) { + // currently selected tab is being replaced so select the new tab before removing the old one + m_stackWidget->setCurrentWidget(tab); + } + // remove and delete old widget + m_stackWidget->removeWidget(wid); + delete wid; } void MyTabbedStackWidget::removeTab(int index) @@ -97,6 +116,7 @@ void MyTabbedStackWidget::removeTab(int index) m_stackWidget->removeWidget(wid); delete wid; + QListWidgetItem *item = m_listWidget->item(index); m_listWidget->removeItemWidget(item); delete item; diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h index 661200383..169eca9ba 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.h @@ -40,6 +40,7 @@ public: MyTabbedStackWidget(QWidget *parent = 0, bool isVertical = false, bool iconAbove = true); void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label); + void replaceTab(int index, QWidget *tab); void removeTab(int index); void setIconSize(int size) { diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 4ae81eb08..368037842 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -166,24 +166,11 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event) void ConfigGadgetWidget::onAutopilotDisconnect() { - int selectedIndex = ftw->currentIndex(); - - QIcon *icon = new QIcon(); - - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new DefaultAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new DefaultHwSettingsWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); - - ftw->setCurrentIndex(selectedIndex); + ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); emit autopilotDisconnected(); } @@ -196,45 +183,26 @@ void ConfigGadgetWidget::onAutopilotConnect() ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectUtilManager *utilMngr = pm->getObject(); if (utilMngr) { - int selectedIndex = ftw->currentIndex(); int board = utilMngr->getBoardModel(); if ((board & 0xff00) == 1024) { // CopterControl family - QIcon *icon = new QIcon(); - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigCCAttitudeWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigCCHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); } else if ((board & 0xff00) == 0x0900) { // Revolution family - - QIcon *icon = new QIcon(); - icon->addFile(":/configgadget/images/ins_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/ins_selected.png", QSize(), QIcon::Selected, QIcon::Off); QWidget *qwd = new ConfigRevoWidget(this); - ftw->removeTab(ConfigGadgetWidget::sensors); - ftw->insertTab(ConfigGadgetWidget::sensors, qwd, *icon, QString("Attitude")); + ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - icon = new QIcon(); - icon->addFile(":/configgadget/images/hardware_normal.png", QSize(), QIcon::Normal, QIcon::Off); - icon->addFile(":/configgadget/images/hardware_selected.png", QSize(), QIcon::Selected, QIcon::Off); qwd = new ConfigRevoHWWidget(this); - ftw->removeTab(ConfigGadgetWidget::hardware); - ftw->insertTab(ConfigGadgetWidget::hardware, qwd, *icon, QString("Hardware")); + ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); } else { // Unknown board qDebug() << "Unknown board " << board; } - ftw->setCurrentIndex(selectedIndex); } emit autopilotConnected(); @@ -284,6 +252,10 @@ void ConfigGadgetWidget::onOPLinkDisconnect() { qDebug() << "ConfigGadgetWidget onOPLinkDisconnect"; oplinkTimeout->stop(); - ftw->removeTab(ConfigGadgetWidget::oplink); oplinkConnected = false; + + if (ftw->currentIndex() == ConfigGadgetWidget::oplink) { + ftw->setCurrentIndex(0); + } + ftw->removeTab(ConfigGadgetWidget::oplink); } From 940074e6f625bfaac9dee2e66cdbe28c2634f14b Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Tue, 13 May 2014 22:06:10 +0200 Subject: [PATCH 50/58] OP-1348 Congig gadget would briefly flash next widget when replacing the currently selected widget (missing change) --- .../openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp index ed1bd75ae..c1e8e8076 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp @@ -82,8 +82,6 @@ MyTabbedStackWidget::MyTabbedStackWidget(QWidget *parent, bool isVertical, bool void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon &icon, const QString &label) { - tab->setContentsMargins(0, 0, 0, 0); - // create and insert item QListWidgetItem *item = new QListWidgetItem(icon, label); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); @@ -91,7 +89,8 @@ void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon & item->setToolTip(label); m_listWidget->insertItem(index, item); - // insert widget + // setup and insert widget + tab->setContentsMargins(0, 0, 0, 0); m_stackWidget->insertWidget(index, tab); } @@ -99,8 +98,10 @@ void MyTabbedStackWidget::replaceTab(int index, QWidget *tab) { QWidget *wid = m_stackWidget->widget(index); - // insert new widget + // setup and insert new widget + tab->setContentsMargins(0, 0, 0, 0); m_stackWidget->insertWidget(index, tab); + // check special case when replacing currenlty selected tab if (index == currentIndex()) { // currently selected tab is being replaced so select the new tab before removing the old one m_stackWidget->setCurrentWidget(tab); From c32026b90602567568eaa47b672e883584b3a6a7 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Tue, 13 May 2014 22:52:10 +0200 Subject: [PATCH 51/58] OP-1331 hopefully last tweaks for input/output channel alignment on CliffOS (most component width are now self adjusting) --- .../src/plugins/config/inputchannelform.ui | 392 +++++++++--------- .../src/plugins/config/outputchannelform.cpp | 4 +- .../src/plugins/config/outputchannelform.ui | 69 ++- 3 files changed, 231 insertions(+), 234 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index b9052fece..965d31003 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -6,7 +6,7 @@ 0 0 - 859 + 853 51 @@ -29,11 +29,107 @@ 12 - - + + true + + + 0 + 0 + + + + + 0 + 20 + + + + + -1 + 75 + false + true + + + + Channel number + + + background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); +color: rgb(255, 255, 255); +border-radius: 5; +font: bold 12px; +margin:1px; + + + QFrame::StyledPanel + + + Number + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 9999 + + + 1000 + + + + + 0 @@ -42,7 +138,88 @@ - 50 + 100 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + 7 + + + + + + + + 0 + 0 + + + + + 80 + 0 + + + + + 16777215 + 16777215 + + + + Text + + + + + + + true + + + + 0 + 0 + + + + + 0 0 @@ -79,151 +256,20 @@ even lead to crash. Use with caution. - - - - - 0 - 0 - - - - - 80 - 0 - - - - - 16777215 - 16777215 - - - - Text - - - - - - - - 0 - 0 - - - - - 90 - 0 - - - - - 16777215 - 16777215 - - - - Qt::StrongFocus - - - 7 - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 16777215 - 16777215 - - - - Qt::StrongFocus - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 16777215 - 16777215 - - - - Qt::StrongFocus - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - QAbstractSpinBox::UpDownArrows - - - 9999 - - - 1000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - true - + 0 0 - 80 + 0 20 @@ -310,14 +356,14 @@ margin:1px; true - + 0 0 - 75 + 0 20 @@ -359,14 +405,14 @@ margin:1px; true - + 0 0 - 50 + 0 20 @@ -408,14 +454,14 @@ margin:1px; true - + 0 0 - 50 + 0 20 @@ -503,14 +549,14 @@ margin:1px; true - + 0 0 - 50 + 0 20 @@ -543,66 +589,20 @@ margin:1px; - - - - true - - - - 0 - 0 - - - - - 90 - 20 - - - - - -1 - 75 - false - true - - - - Channel number - - - background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255)); -color: rgb(255, 255, 255); -border-radius: 5; -font: bold 12px; -margin:1px; - - - QFrame::StyledPanel - - - Number - - - Qt::AlignCenter - - - true - + 0 0 - 100 + 0 20 @@ -638,14 +638,14 @@ margin:1px; - + 0 0 - 50 + 0 0 @@ -749,7 +749,7 @@ margin:1px; - 60 + 16777215 16777215 diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp index da8514855..0ca1ecaf7 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.cpp @@ -269,7 +269,7 @@ void OutputChannelForm::sendChannelTest(int value) value = ui.actuatorMin->value() - value + ui.actuatorMax->value(); } // update the label - ui.actuatorValue->setText(QString::number(value)); + ui.actuatorValue->setValue(value); if (ui.actuatorLink->checkState() && parent()) { // the channel is linked to other channels @@ -296,7 +296,7 @@ void OutputChannelForm::sendChannelTest(int value) } outputChannelForm->ui.actuatorNeutral->setValue(val); - outputChannelForm->ui.actuatorValue->setText(QString::number(val)); + outputChannelForm->ui.actuatorValue->setValue(val); } } diff --git a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui index da55a432b..f6227939a 100644 --- a/ground/openpilotgcs/src/plugins/config/outputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/outputchannelform.ui @@ -6,7 +6,7 @@ 0 0 - 772 + 768 51 @@ -32,14 +32,14 @@ - + 0 0 - 110 + 0 20 @@ -75,14 +75,14 @@ margin:1px; - + 0 0 - 50 + 0 20 @@ -171,14 +171,14 @@ margin:1px; - + 0 0 - 20 + 0 20 @@ -268,14 +268,14 @@ margin:1px; - + 0 0 - 50 + 0 0 @@ -336,14 +336,14 @@ margin:1px; - + 0 0 - 50 + 0 20 @@ -379,14 +379,14 @@ margin:1px; - + 0 0 - 75 + 0 20 @@ -422,14 +422,14 @@ margin:1px; - + 0 0 - 45 + 0 20 @@ -493,14 +493,14 @@ margin:1px; - + 0 0 - 50 + 0 0 @@ -577,34 +577,31 @@ margin:1px; - + + + true + - + 0 0 - - - 25 - 0 - - - - - 16777215 - 16777215 - - - - Current value of slider. - - - 0000 + + true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + true + + + QAbstractSpinBox::UpDownArrows + + + 9999 + From b74e1c19bf711dd3a169f2438d761696507cbceb Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Wed, 14 May 2014 22:11:15 +0200 Subject: [PATCH 52/58] OP-1331 slightly increased min width of Input Channel Type and Number comboboxes --- .../src/plugins/config/inputchannelform.ui | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index 965d31003..856b4d41b 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -6,7 +6,7 @@ 0 0 - 853 + 923 51 @@ -131,7 +131,35 @@ margin:1px; - + + 0 + 0 + + + + + 110 + 0 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + QComboBox::AdjustToContents + + + + + + + 0 0 @@ -151,40 +179,18 @@ margin:1px; Qt::StrongFocus - - - - - - - 0 - 0 - - - - - 90 - 0 - - - - - 16777215 - 16777215 - - - - Qt::StrongFocus - 7 + + QComboBox::AdjustToContents + - + 0 0 From 8caac790ef0ef73d4fffc702893e84b77ee3f193 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Wed, 14 May 2014 22:32:47 +0200 Subject: [PATCH 53/58] ignore Eclipse project files ground/openpilotgcs --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0deef206c..e2c9b04d7 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ core # ground openpilotgcs-build-desktop +ground/openpilotgcs/.cproject +ground/openpilotgcs/.project +ground/openpilotgcs/.settings # Ignore some of the .pro.user files *.pro.user From ced787d71616ccab2ce2718094e4884fcc2fb041 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Wed, 14 May 2014 23:37:40 +0200 Subject: [PATCH 54/58] OP-1331 fixed regression in widget binding framework (handling of scale was broken) --- .../uavobjectwidgetutils/configtaskwidget.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index 19c9ff8fb..714de84d7 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -406,24 +406,23 @@ void ConfigTaskWidget::widgetsContentsChanged() { QWidget *emitter = ((QWidget *)sender()); emit widgetContentsChanged(emitter); - double scale = 1.0; QVariant value; foreach(WidgetBinding * binding, m_widgetBindingsPerWidget.values(emitter)) { if (binding && binding->isEnabled()) { if (binding->widget() == emitter) { - checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), - getVariantFromWidget(emitter, binding), binding->scale()); + value = getVariantFromWidget(emitter, binding); + checkWidgetsLimits(emitter, binding->field(), binding->index(), binding->isLimited(), value, binding->scale()); } else { foreach(ShadowWidgetBinding * shadow, binding->shadows()) { if (shadow->widget() == emitter) { - WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), binding->index(), shadow->scale(), shadow->isLimited()); - QVariant value = getVariantFromWidget(emitter, &tmpBinding); - checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), value, scale); + WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), + binding->index(), shadow->scale(), shadow->isLimited()); + value = getVariantFromWidget(emitter, &tmpBinding); + checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), value, shadow->scale()); } } } - value = getVariantFromWidget(emitter, binding); binding->setValue(value); if (binding->widget() != emitter) { From 9fe0c6516cd27ab699a9b395d342f39bd68fb384 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Thu, 15 May 2014 00:20:45 +0200 Subject: [PATCH 55/58] OP-1331 slightly increased min width of Input Channel Function combobox --- ground/openpilotgcs/src/plugins/config/inputchannelform.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui index 856b4d41b..2f4db720c 100644 --- a/ground/openpilotgcs/src/plugins/config/inputchannelform.ui +++ b/ground/openpilotgcs/src/plugins/config/inputchannelform.ui @@ -197,7 +197,7 @@ margin:1px; - 80 + 100 0 From 2357ee1774bb8aa79b9845e4b5d67e4da296713d Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Fri, 16 May 2014 23:39:36 +0200 Subject: [PATCH 56/58] hotfix: allow arming in Stabilized 4,5,6 --- flight/modules/ManualControl/armhandler.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flight/modules/ManualControl/armhandler.c b/flight/modules/ManualControl/armhandler.c index b16f1e39b..76833678e 100644 --- a/flight/modules/ManualControl/armhandler.c +++ b/flight/modules/ManualControl/armhandler.c @@ -274,6 +274,9 @@ static bool okToArm(void) case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED4: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED5: + case FLIGHTSTATUS_FLIGHTMODE_STABILIZED6: return true; break; From 2d4ad5a76d49e19b12bc3f172af8acc9cbadba73 Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Fri, 16 May 2014 23:42:17 +0200 Subject: [PATCH 57/58] uncrustification --- ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp | 1 + .../openpilotgcs/src/plugins/config/configgadgetwidget.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp index c1e8e8076..bc31f58c0 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp @@ -84,6 +84,7 @@ void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon & { // create and insert item QListWidgetItem *item = new QListWidgetItem(icon, label); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); item->setToolTip(label); diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 368037842..3b80223b3 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -167,9 +167,10 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event) void ConfigGadgetWidget::onAutopilotDisconnect() { QWidget *qwd = new DefaultAttitudeWidget(this); + ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new DefaultHwSettingsWidget(this); + qwd = new DefaultHwSettingsWidget(this); ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); emit autopilotDisconnected(); @@ -190,14 +191,14 @@ void ConfigGadgetWidget::onAutopilotConnect() QWidget *qwd = new ConfigCCAttitudeWidget(this); ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new ConfigCCHWWidget(this); + qwd = new ConfigCCHWWidget(this); ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); } else if ((board & 0xff00) == 0x0900) { // Revolution family QWidget *qwd = new ConfigRevoWidget(this); ftw->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new ConfigRevoHWWidget(this); + qwd = new ConfigRevoHWWidget(this); ftw->replaceTab(ConfigGadgetWidget::hardware, qwd); } else { // Unknown board From fe60509ffa1c05c35e267f7beed9ca73dc5620f3 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Fri, 16 May 2014 23:53:04 +0200 Subject: [PATCH 58/58] OP-1331 uncrustified --- ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp | 1 + .../openpilotgcs/src/plugins/config/configgadgetwidget.cpp | 7 ++++--- .../src/plugins/uavobjectwidgetutils/configtaskwidget.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp index c1e8e8076..bc31f58c0 100644 --- a/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp +++ b/ground/openpilotgcs/src/libs/utils/mytabbedstackwidget.cpp @@ -84,6 +84,7 @@ void MyTabbedStackWidget::insertTab(const int index, QWidget *tab, const QIcon & { // create and insert item QListWidgetItem *item = new QListWidgetItem(icon, label); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); item->setToolTip(label); diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index 2cb8b4e86..cd359019b 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -165,9 +165,10 @@ void ConfigGadgetWidget::resizeEvent(QResizeEvent *event) void ConfigGadgetWidget::onAutopilotDisconnect() { QWidget *qwd = new DefaultAttitudeWidget(this); + stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new DefaultHwSettingsWidget(this); + qwd = new DefaultHwSettingsWidget(this); stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); emit autopilotDisconnected(); @@ -187,14 +188,14 @@ void ConfigGadgetWidget::onAutopilotConnect() QWidget *qwd = new ConfigCCAttitudeWidget(this); stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new ConfigCCHWWidget(this); + qwd = new ConfigCCHWWidget(this); stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); } else if ((board & 0xff00) == 0x0900) { // Revolution family QWidget *qwd = new ConfigRevoWidget(this); stackWidget->replaceTab(ConfigGadgetWidget::sensors, qwd); - qwd = new ConfigRevoHWWidget(this); + qwd = new ConfigRevoHWWidget(this); stackWidget->replaceTab(ConfigGadgetWidget::hardware, qwd); } else { // Unknown board diff --git a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp index 3ccb02391..6df939d0a 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectwidgetutils/configtaskwidget.cpp @@ -389,7 +389,7 @@ void ConfigTaskWidget::widgetsContentsChanged() foreach(ShadowWidgetBinding * shadow, binding->shadows()) { if (shadow->widget() == emitter) { WidgetBinding tmpBinding(shadow->widget(), binding->object(), binding->field(), - binding->index(), shadow->scale(), shadow->isLimited()); + binding->index(), shadow->scale(), shadow->isLimited()); value = getVariantFromWidget(emitter, &tmpBinding); checkWidgetsLimits(emitter, binding->field(), binding->index(), shadow->isLimited(), value, shadow->scale()); }