diff --git a/Makefile b/Makefile index 3cb5c53bb..7ae15391d 100644 --- a/Makefile +++ b/Makefile @@ -638,7 +638,7 @@ uavo-collections_clean: # ############################## -ALL_UNITTESTS := logfs math +ALL_UNITTESTS := logfs math lednotification # Build the directory for the unit tests UT_OUT_DIR := $(BUILD_DIR)/unit_tests diff --git a/flight/libraries/inc/lednotification.h b/flight/libraries/inc/lednotification.h new file mode 100644 index 000000000..fadd100f0 --- /dev/null +++ b/flight/libraries/inc/lednotification.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * + * @file lednotification.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief led 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 LEDNOTIFICATION_H_ +#define LEDNOTIFICATION_H_ +#include + +void LedNotificationExtLedsRun(); + + +#endif /* LEDNOTIFICATION_H_ */ diff --git a/flight/libraries/inc/notification.h b/flight/libraries/inc/notification.h index 2053a9609..2091d9189 100644 --- a/flight/libraries/inc/notification.h +++ b/flight/libraries/inc/notification.h @@ -27,7 +27,7 @@ #define NOTIFICATION_H // period of each blink phase -#define LED_BLINK_PERIOD_MS 200 +#define LED_BLINK_PERIOD_MS 50 // update the status snapshot used by notifcations void NotificationUpdateStatus(); diff --git a/flight/libraries/inc/optypes.h b/flight/libraries/inc/optypes.h new file mode 100644 index 000000000..6b9080db7 --- /dev/null +++ b/flight/libraries/inc/optypes.h @@ -0,0 +1,64 @@ +/** + ****************************************************************************** + * + * @file optypes.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief OP Generic data type 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 UTIL_H +#define UTIL_H +#include +typedef struct { + uint8_t R; + uint8_t G; + uint8_t B; +} Color_t; + +extern const Color_t Color_Off; +extern const Color_t Color_Black; +extern const Color_t Color_Red; +extern const Color_t Color_Lime; +extern const Color_t Color_Blue; +extern const Color_t Color_Yellow; +extern const Color_t Color_Cian; +extern const Color_t Color_Magenta; +extern const Color_t Color_Navy; +extern const Color_t Color_Green; +extern const Color_t Color_Purple; +extern const Color_t Color_Teal; +extern const Color_t Color_Orange; +extern const Color_t Color_White; + +#define COLOR_BLACK { .R = 0x00, .G = 0x00, .B = 0x00 } +#define COLOR_OFF COLOR_BLACK +#define COLOR_RED { .R = 0xFF, .G = 0x00, .B = 0x00 } +#define COLOR_LIME { .R = 0x00, .G = 0xFF, .B = 0x00 } +#define COLOR_BLUE { .R = 0x00, .G = 0x00, .B = 0xFF } +#define COLOR_YELLOW { .R = 0xFF, .G = 0xFF, .B = 0x00 } +#define COLOR_CIAN { .R = 0x00, .G = 0xFF, .B = 0xFF } +#define COLOR_MAGENTA { .R = 0xFF, .G = 0x00, .B = 0xFF } +#define COLOR_NAVY { .R = 0x00, .G = 0x00, .B = 0x80 } +#define COLOR_GREEN { .R = 0x00, .G = 0x80, .B = 0x00 } +#define COLOR_PURPLE { .R = 0x80, .G = 0x00, .B = 0x80 } +#define COLOR_TEAL { .R = 0x00, .G = 0x80, .B = 0x80 } +#define COLOR_ORANGE { .R = 0xFF, .G = 0xA5, .B = 0x00 } +#define COLOR_WHITE { .R = 0xAA, .G = 0xAA, .B = 0xAA } +#endif /* UTIL_H */ diff --git a/flight/libraries/lednotification.c b/flight/libraries/lednotification.c new file mode 100644 index 000000000..e6d961747 --- /dev/null +++ b/flight/libraries/lednotification.c @@ -0,0 +1,259 @@ +/** + ****************************************************************************** + * + * @file lednotification.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief led 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 + */ +#include "inc/lednotification.h" +#include +#include +#include +#include +#include +#include +#include + +// Private defines + +// Maximum number of notifications enqueued when a higher priority notification is added +#define MAX_BACKGROUND_NOTIFICATIONS 6 +#define MAX_HANDLED_LED 1 + +#define BACKGROUND_SEQUENCE 0 +#define RESET_STEP -1 +#define GET_CURRENT_MILLIS (xTaskGetTickCount() * portTICK_RATE_MS) + +// Private data types definition +// this is the status for a single notification led set +typedef struct { + int8_t queued_priorities[MAX_BACKGROUND_NOTIFICATIONS]; // slot 0 is reserved for background + LedSequence_t queued_sequences[MAX_BACKGROUND_NOTIFICATIONS]; // slot 0 is reserved for background + uint32_t next_run_time; + uint32_t sequence_starting_time; + + int8_t active_sequence_num; // active queued sequence or BACKGROUND_SEQUENCE + bool running; // is this led running? + bool step_phase_on; // true = step on phase, false = step off phase + uint8_t next_sequence_step; // (step number to be executed) << 1 || (0x00 = on phase, 0x01 = off phase) + uint8_t next_step_rep; // next repetition number for next step (valid if step.repeats >1) + uint8_t next_sequence_rep; // next sequence repetition counter (valid if sequence.repeats > 1) + uint8_t led_set_start; // first target led for this set + uint8_t led_set_end; // last target led for this set +} NotifierLedStatus_t; + +static bool led_status_initialized = false; + +NotifierLedStatus_t led_status[MAX_HANDLED_LED]; + +static void InitExtLed() +{ + memset(led_status, 0, sizeof(NotifierLedStatus_t) * MAX_HANDLED_LED); + const uint32_t now = GET_CURRENT_MILLIS; + for (uint8_t l = 0; l < MAX_HANDLED_LED; l++) { + led_status[l].led_set_start = 0; + led_status[l].led_set_end = PIOS_WS2811_NUMLEDS - 1; + led_status[l].next_run_time = now + 500; // start within half a second + for (uint8_t i = 0; i < MAX_BACKGROUND_NOTIFICATIONS; i++) { + led_status[l].queued_priorities[i] = NOTIFY_PRIORITY_BACKGROUND; + } + } +} + +/** + * restart current sequence + */ +static void restart_sequence(NotifierLedStatus_t *status, bool immediate) +{ + status->next_sequence_step = 0; + status->next_step_rep = 0; + status->step_phase_on = true; + status->running = true; + if (immediate) { + uint32_t currentTime = GET_CURRENT_MILLIS; + status->next_run_time = currentTime; + } + status->sequence_starting_time = status->next_run_time; +} + +/** + * modify background sequence or enqueue a new sequence to play + */ +static void push_queued_sequence(ExtLedNotification_t *new_notification, NotifierLedStatus_t *status) +{ + int8_t updated_sequence; + + int8_t lowest_priority_index = -1; + int8_t lowest_priority = new_notification->priority; + + if (new_notification->priority == NOTIFY_PRIORITY_BACKGROUND) { + lowest_priority_index = BACKGROUND_SEQUENCE; + } else { + // slot 0 is reserved for Background sequence + for (int8_t i = 1; i < MAX_BACKGROUND_NOTIFICATIONS; i++) { + if (status->queued_priorities[i] < lowest_priority) { + lowest_priority_index = i; + lowest_priority = status->queued_priorities[i]; + } + } + } + + // no items with priority lower than the one we are trying to enqueue. skip + if (lowest_priority_index < 0) { + return; + } + + status->queued_priorities[lowest_priority_index] = new_notification->priority; + status->queued_sequences[lowest_priority_index] = new_notification->sequence; + updated_sequence = lowest_priority_index;; + + + // check whether we should preempt the current notification and play this new one + if (status->queued_priorities[status->active_sequence_num] < new_notification->priority) { + status->active_sequence_num = updated_sequence; + } + + if (status->active_sequence_num == updated_sequence) { + restart_sequence(status, true); + } +} + +static bool pop_queued_sequence(NotifierLedStatus_t *status) +{ + if (status->active_sequence_num > BACKGROUND_SEQUENCE) { + // set the last active slot as empty + status->queued_priorities[status->active_sequence_num] = NOTIFY_PRIORITY_BACKGROUND; + + // search the highest priority item + int8_t highest_priority_index = BACKGROUND_SEQUENCE; + int8_t highest_priority = NOTIFY_PRIORITY_BACKGROUND; + + for (int8_t i = 1; i < MAX_BACKGROUND_NOTIFICATIONS; i++) { + if (status->queued_priorities[i] > highest_priority) { + highest_priority_index = i; + highest_priority = status->queued_priorities[i]; + } + } + // set the next sequence to activate (or BACKGROUND_SEQUENCE when all slots are empty) + status->active_sequence_num = highest_priority_index; + return highest_priority_index != BACKGROUND_SEQUENCE; + } + // background sequence was completed + return false; +} + +/** + * advance current sequence pointers for next step + */ +static void advance_sequence(NotifierLedStatus_t *status) +{ + LedSequence_t *activeSequence = &status->queued_sequences[status->active_sequence_num]; + + uint8_t step = status->next_sequence_step; + LedStep_t *currentStep = &activeSequence->steps[step]; + + // Next step will be the OFF phase, so just update the time and + if (status->step_phase_on) { + // next will be the off phase + status->next_run_time += currentStep->time_on; + status->step_phase_on = false; + // check if off phase should be skipped + if (currentStep->time_off != 0) { + return; + } + } + + // next step is ON phase. check whether to repeat current step or move to next one + status->next_run_time += currentStep->time_off; + status->step_phase_on = true; + + if (status->next_step_rep + 1 < currentStep->repeats) { + // setup next repetition + status->next_step_rep++; + return; + } + + // move to next step + LedStep_t *nextStep = (step + 1 < NOTIFY_SEQUENCE_MAX_STEPS) ? &activeSequence->steps[step + 1] : 0; + + // next step is null, check whether sequence must be repeated or it must move to lower priority queued or background sequences + if (NOTIFY_IS_NULL_STEP(nextStep)) { + if (activeSequence->repeats == -1 || status->next_sequence_rep + 1 < activeSequence->repeats) { + status->next_sequence_rep++; + // restart the sequence + restart_sequence(status, false); + return; + } + if (status->active_sequence_num != BACKGROUND_SEQUENCE) { + // no repeat, pop enqueued or background sequences + pop_queued_sequence(status); + restart_sequence(status, false); + status->next_sequence_rep = 0; + } else { + status->running = false; + } + } else { + status->next_step_rep = 0; + status->next_sequence_step++; + } +} + +/** + * run a led set + */ +static void run_led(NotifierLedStatus_t *status) +{ + const uint32_t currentTime = GET_CURRENT_MILLIS; + + if (!status->running || currentTime < status->next_run_time) { + return; + } + status->next_run_time = currentTime; + uint8_t step = status->next_sequence_step; + + LedSequence_t *activeSequence = &status->queued_sequences[status->active_sequence_num]; + const Color_t color = status->step_phase_on ? activeSequence->steps[step].color : Color_Off; + + for (uint8_t i = status->led_set_start; i <= status->led_set_end; i++) { + PIOS_WS2811_setColorRGB(color, i, false); + } + PIOS_WS2811_Update(); + advance_sequence(status); +} + +void LedNotificationExtLedsRun() +{ + // handle incoming sequences + if (!led_status_initialized) { + InitExtLed(); + led_status_initialized = true; + } + static ExtLedNotification_t *newNotification; + newNotification = PIOS_NOTIFY_GetNewExtLedSequence(true); + if (newNotification) { + push_queued_sequence(newNotification, &led_status[0]); + } + + // Run Leds + for (uint8_t i = 0; i < MAX_HANDLED_LED; i++) { + run_led(&led_status[i]); + } +} diff --git a/flight/libraries/notification.c b/flight/libraries/notification.c index 2d11d224a..f68504048 100644 --- a/flight/libraries/notification.c +++ b/flight/libraries/notification.c @@ -28,6 +28,11 @@ #include #include #include +#include + + +#define GET_CURRENT_MILLIS (xTaskGetTickCount() * portTICK_RATE_MS) +// Private data types definition #ifdef PIOS_LED_ALARM #define ALARM_LED_ON() PIOS_LED_On(PIOS_LED_ALARM) @@ -136,6 +141,8 @@ static bool handleAlarms(uint16_t *r_pattern, uint16_t *b_pattern); static bool handleNotifications(pios_notify_notification runningNotification, 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; @@ -149,7 +156,7 @@ void NotificationUpdateStatus() void NotificationOnboardLedsRun() { - static portTickType lastRunTimestamp; + static uint32_t lastRunTimestamp; static uint16_t r_pattern; static uint16_t b_pattern; static uint8_t cycleCount; // count the number of cycles @@ -163,11 +170,13 @@ void NotificationOnboardLedsRun() STATUS_LENGHT } status; - if (!started || (xTaskGetTickCount() - lastRunTimestamp) < (LED_BLINK_PERIOD_MS * portTICK_RATE_MS / 4)) { + const uint32_t current_timestamp = GET_CURRENT_MILLIS; + + if (!started || (current_timestamp - lastRunTimestamp) < LED_BLINK_PERIOD_MS) { return; } - lastRunTimestamp = xTaskGetTickCount(); + lastRunTimestamp = current_timestamp; // the led will show various status information, subdivided in three phases // - Notification // - Alarm diff --git a/flight/libraries/optypes.c b/flight/libraries/optypes.c new file mode 100644 index 000000000..3b2c7b728 --- /dev/null +++ b/flight/libraries/optypes.c @@ -0,0 +1,42 @@ +/** + ****************************************************************************** + * + * @file optypes.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @brief OP Generic data type 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 + */ + +#include + +const Color_t Color_Off = COLOR_OFF; +const Color_t Color_Black = COLOR_BLACK; +const Color_t Color_Red = COLOR_RED; +const Color_t Color_Lime = COLOR_LIME; +const Color_t Color_Blue = COLOR_BLUE; +const Color_t Color_Yellow = COLOR_YELLOW; +const Color_t Color_Cian = COLOR_CIAN; +const Color_t Color_Magenta = COLOR_MAGENTA; +const Color_t Color_Navy = COLOR_NAVY; +const Color_t Color_Green = COLOR_GREEN; +const Color_t Color_Purple = COLOR_PURPLE; +const Color_t Color_Teal = COLOR_TEAL; +const Color_t Color_Orange = COLOR_ORANGE; +const Color_t Color_White = COLOR_WHITE; diff --git a/flight/modules/GPS/GPS.c b/flight/modules/GPS/GPS.c index 9729c5189..e8524fd2e 100644 --- a/flight/modules/GPS/GPS.c +++ b/flight/modules/GPS/GPS.c @@ -245,7 +245,9 @@ static void gpsTask(__attribute__((unused)) void *parameters) if (gpsSettings.DataProtocol == GPSSETTINGS_DATAPROTOCOL_UBX) { char *buffer = 0; uint16_t count = 0; - ubx_autoconfig_run(&buffer, &count); + uint8_t status; + GPSPositionSensorStatusGet(&status); + ubx_autoconfig_run(&buffer, &count, status != GPSPOSITIONSENSOR_STATUS_NOGPS); // Something to send? if (count) { PIOS_COM_SendBuffer(gpsPort, (uint8_t *)buffer, count); @@ -266,11 +268,17 @@ static void gpsTask(__attribute__((unused)) void *parameters) { #if defined(PIOS_INCLUDE_GPS_UBX_PARSER) && !defined(PIOS_GPS_MINIMAL) int32_t ac_status = ubx_autoconfig_get_status(); + static uint8_t lastStatus = 0; + gpspositionsensor.AutoConfigStatus = ac_status == UBX_AUTOCONFIG_STATUS_DISABLED ? GPSPOSITIONSENSOR_AUTOCONFIGSTATUS_DISABLED : ac_status == UBX_AUTOCONFIG_STATUS_DONE ? GPSPOSITIONSENSOR_AUTOCONFIGSTATUS_DONE : ac_status == UBX_AUTOCONFIG_STATUS_ERROR ? GPSPOSITIONSENSOR_AUTOCONFIGSTATUS_ERROR : GPSPOSITIONSENSOR_AUTOCONFIGSTATUS_RUNNING; + if (gpspositionsensor.AutoConfigStatus != lastStatus) { + GPSPositionSensorAutoConfigStatusSet(&gpspositionsensor.AutoConfigStatus); + lastStatus = gpspositionsensor.AutoConfigStatus; + } #endif res = parse_ubx_stream(c, gps_rx_buffer, &gpspositionsensor, &gpsRxStats); } @@ -290,7 +298,8 @@ static void gpsTask(__attribute__((unused)) void *parameters) // Check for GPS timeout timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS; - if ((timeNowMs - timeOfLastUpdateMs) >= GPS_TIMEOUT_MS) { + if ((timeNowMs - timeOfLastUpdateMs) >= GPS_TIMEOUT_MS || + (gpsSettings.DataProtocol == GPSSETTINGS_DATAPROTOCOL_UBX && gpspositionsensor.AutoConfigStatus == GPSPOSITIONSENSOR_AUTOCONFIGSTATUS_ERROR)) { // we have not received any valid GPS sentences for a while. // either the GPS is not plugged in or a hardware problem or the GPS has locked up. uint8_t status = GPSPOSITIONSENSOR_STATUS_NOGPS; diff --git a/flight/modules/GPS/UBX.c b/flight/modules/GPS/UBX.c index ba417b5ac..c883e7a39 100644 --- a/flight/modules/GPS/UBX.c +++ b/flight/modules/GPS/UBX.c @@ -515,6 +515,14 @@ uint32_t parse_ubx_message(struct UBXPacket *ubx, GPSPositionSensorData *GpsPosi GPSPositionSensorSet(GpsPosition); msgtracker.msg_received = NONE_RECEIVED; id = GPSPOSITIONSENSOR_OBJID; + } else { + uint8_t status; + GPSPositionSensorStatusGet(&status); + if (status == GPSPOSITIONSENSOR_STATUS_NOGPS) { + // Some ubx thing has been received so GPS is there + status = GPSPOSITIONSENSOR_STATUS_NOFIX; + GPSPositionSensorStatusSet(&status); + } } return id; } diff --git a/flight/modules/GPS/inc/ubx_autoconfig.h b/flight/modules/GPS/inc/ubx_autoconfig.h index e01391a7d..734c54537 100644 --- a/flight/modules/GPS/inc/ubx_autoconfig.h +++ b/flight/modules/GPS/inc/ubx_autoconfig.h @@ -33,13 +33,20 @@ // defines // TODO: NEO8 max rate is for Rom version, flash is limited to 10Hz, need to handle that. -#define UBX_MAX_RATE_VER8 18 -#define UBX_MAX_RATE_VER7 10 -#define UBX_MAX_RATE 5 - -#define UBX_REPLY_TIMEOUT (500 * 1000) -#define UBX_MAX_RETRIES 5 +#define UBX_MAX_RATE_VER8 18 +#define UBX_MAX_RATE_VER7 10 +#define UBX_MAX_RATE 5 +// time to wait before reinitializing the fsm due to disconnection +#define UBX_CONNECTION_TIMEOUT (2000 * 1000) +// times between retries in case an error does occurs +#define UBX_ERROR_RETRY_TIMEOUT (1000 * 1000) +// timeout for ack reception +#define UBX_REPLY_TIMEOUT (500 * 1000) +// max retries in case of timeout +#define UBX_MAX_RETRIES 5 +// pause between each configuration step +#define UBX_STEP_WAIT_TIME (10 * 1000) // types typedef enum { UBX_AUTOCONFIG_STATUS_DISABLED = 0, @@ -179,7 +186,7 @@ typedef union { } message; } __attribute__((packed)) UBXSentPacket_t; -void ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send); +void ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send, bool gps_connected); void ubx_autoconfig_set(ubx_autoconfig_settings_t config); int32_t ubx_autoconfig_get_status(); #endif /* UBX_AUTOCONFIG_H_ */ diff --git a/flight/modules/GPS/ubx_autoconfig.c b/flight/modules/GPS/ubx_autoconfig.c index 74aa89179..1671b601a 100644 --- a/flight/modules/GPS/ubx_autoconfig.c +++ b/flight/modules/GPS/ubx_autoconfig.c @@ -46,6 +46,7 @@ typedef enum { typedef struct { initSteps_t currentStep; // Current configuration "fsm" status uint32_t lastStepTimestampRaw; // timestamp of last operation + uint32_t lastConnectedRaw; // timestamp of last time gps was connected UBXSentPacket_t working_packet; // outbound "buffer" ubx_autoconfig_settings_t currentSettings; int8_t lastConfigSent; // index of last configuration string sent @@ -227,7 +228,7 @@ void config_save(uint16_t *bytes_to_send) { memset(status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_cfg_t)); // mask LSB=ioPort|msgConf|infMsg|navConf|rxmConf|||||rinvConf|antConf|....|= MSB - status->working_packet.message.payload.cfg_cfg.saveMask = 0x01 | 0x08; // msgConf + navConf + status->working_packet.message.payload.cfg_cfg.saveMask = 0x02 | 0x08; // msgConf + navConf status->working_packet.message.payload.cfg_cfg.deviceMask = UBX_CFG_CFG_ALL_DEVICES_MASK; *bytes_to_send = prepare_packet(&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_CFG, sizeof(ubx_cfg_cfg_t)); status->requiredAck.clsID = UBX_CLASS_CFG; @@ -279,21 +280,50 @@ static void enable_sentences(__attribute__((unused)) uint16_t *bytes_to_send) } } -void ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send) +void ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send, bool gps_connected) { *bytes_to_send = 0; *buffer = (char *)status->working_packet.buffer; - if (!status || !enabled) { + if (!status || !enabled || status->currentStep == INIT_STEP_DISABLED) { return; // autoconfig not enabled } + if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_STEP_WAIT_TIME) { + return; + } + // when gps is disconnected it will replay the autoconfig sequence. + if (!gps_connected) { + if (status->currentStep == INIT_STEP_DONE) { + // if some operation is in progress and it is not running into issues it maybe that + // the disconnection is only due to wrong message rates, so reinit only when done. + // errors caused by disconnection are handled by error retry logic + if (PIOS_DELAY_DiffuS(status->lastConnectedRaw) > UBX_CONNECTION_TIMEOUT) { + status->currentStep = INIT_STEP_START; + return; + } + } + } else { + // reset connection timer + status->lastConnectedRaw = PIOS_DELAY_GetRaw(); + } + switch (status->currentStep) { - case INIT_STEP_ERROR: // TODO: what to do? retries after a while? maybe gps was disconnected (this can be detected)? + case INIT_STEP_ERROR: + if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) > UBX_ERROR_RETRY_TIMEOUT) { + status->currentStep = INIT_STEP_START; + status->lastStepTimestampRaw = PIOS_DELAY_GetRaw(); + } + return; + case INIT_STEP_DISABLED: case INIT_STEP_DONE: return; case INIT_STEP_START: case INIT_STEP_ASK_VER: + // clear ack + ubxLastAck.clsID = 0x00; + ubxLastAck.msgID = 0x00; + status->lastStepTimestampRaw = PIOS_DELAY_GetRaw(); build_request(&status->working_packet, UBX_CLASS_MON, UBX_ID_MON_VER, bytes_to_send); status->currentStep = INIT_STEP_WAIT_VER; @@ -348,6 +378,7 @@ void ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send) status->retryCount++; if (status->retryCount > UBX_MAX_RETRIES) { status->currentStep = INIT_STEP_ERROR; + status->lastStepTimestampRaw = PIOS_DELAY_GetRaw(); return; } } @@ -374,12 +405,16 @@ void ubx_autoconfig_set(ubx_autoconfig_settings_t config) status->currentSettings = config; status->currentStep = INIT_STEP_START; enabled = true; + } else { + if (!status) { + status->currentStep = INIT_STEP_DISABLED; + } } } int32_t ubx_autoconfig_get_status() { - if (!status) { + if (!status || !enabled) { return UBX_AUTOCONFIG_STATUS_DISABLED; } switch (status->currentStep) { diff --git a/flight/modules/Notify/inc/notify.h b/flight/modules/Notify/inc/notify.h new file mode 100644 index 000000000..1b779bf27 --- /dev/null +++ b/flight/modules/Notify/inc/notify.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * + * @file notify.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Notify module, show events and status on external led. + * + * @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 NOTIFY_H_ +#define NOTIFY_H_ + + +int32_t NotifyInitialize(void); + + +#endif /* NOTIFY_H_ */ diff --git a/flight/modules/Notify/inc/sequences.h b/flight/modules/Notify/inc/sequences.h new file mode 100644 index 000000000..c28f90c15 --- /dev/null +++ b/flight/modules/Notify/inc/sequences.h @@ -0,0 +1,222 @@ +/** + ****************************************************************************** + * + * @file sequences.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Notify module, sequences configuration. + * + * @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 SEQUENCES_H_ +#define SEQUENCES_H_ +#include +#include +#include +#include +#include + +// This represent the list of basic light sequences, defined later +typedef enum { + NOTIFY_SEQUENCE_ARMED_FM_MANUAL = 0, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED1 = 1, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED2 = 2, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED3 = 3, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED4 = 4, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED5 = 5, + NOTIFY_SEQUENCE_ARMED_FM_STABILIZED6 = 6, + NOTIFY_SEQUENCE_ARMED_FM_AUTOTUNE = 7, + NOTIFY_SEQUENCE_ARMED_FM_GPS = 8, + NOTIFY_SEQUENCE_ARMED_FM_RTH = 9, + NOTIFY_SEQUENCE_ARMED_FM_LAND = 10, + NOTIFY_SEQUENCE_ARMED_FM_AUTO = 11, + NOTIFY_SEQUENCE_ALM_WARN_GPS = 12, + NOTIFY_SEQUENCE_ALM_ERROR_GPS = 13, + NOTIFY_SEQUENCE_ALM_WARN_BATTERY = 14, + NOTIFY_SEQUENCE_ALM_ERROR_BATTERY = 15, + NOTIFY_SEQUENCE_ALM_MAG = 16, + NOTIFY_SEQUENCE_ALM_CONFIG = 17, + NOTIFY_SEQUENCE_ALM_RECEIVER = 18, + NOTIFY_SEQUENCE_DISARMED = 19, + NOTIFY_SEQUENCE_NULL = 255, // skips any signalling for this condition +} NotifySequences; + +// This structure determine sequences attached to an alarm +typedef struct { + uint32_t timeBetweenNotifications; // time in milliseconds to wait between each notification iteration + uint8_t alarmIndex; // Index of the alarm, use one of the SYSTEMALARMS_ALARM_XXXXX defines + uint8_t warnNotification; // index of the sequence to be used when alarm is in warning status(pick one from NotifySequences enum) + uint8_t errorNotification; // index of the sequence to be used when alarm is in error status(pick one from NotifySequences enum) +} AlarmDefinition_t; + + +// This is the list of defined light sequences +/* how each sequence is defined + * [NOTIFY_SEQUENCE_DISARMED] = { // Sequence ID + .repeats = -1, // Number of repetitions or -1 for infinite + .steps = { // List of steps (until NOTIFY_SEQUENCE_MAX_STEPS steps, default to 5) + { + .time_off = 500, // Off time for the step + .time_on = 500, // On time for the step + .color = COLOR_TEAL, // color + .repeats = 1, // repetitions for this step + }, + }, + }, + * + * There are two kind of sequences: + * - "Background" sequences, executed if no higher priority sequence is played; + * - "Alarm" sequences, that are "modal", they temporarily suspends background sequences and plays. + * Cannot have "-1" repetitions + * At the end background sequence are resumed; + * + */ +const LedSequence_t notifications[] = { + [NOTIFY_SEQUENCE_DISARMED] = { .repeats = -1, .steps = { + { .time_off = 500, .time_on = 500, .color = COLOR_TEAL, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_MANUAL] = { .repeats = -1, .steps = { + { .time_off = 900, .time_on = 100, .color = COLOR_YELLOW, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED1] = { .repeats = -1, .steps = { + { .time_off = 900, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED2] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + { .time_off = 700, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED3] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_BLUE, .repeats = 2, }, + { .time_off = 500, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED4] = { .repeats = -1, .steps = { + { .time_off = 900, .time_on = 100, .color = COLOR_PURPLE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED5] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_PURPLE, .repeats = 1, }, + { .time_off = 700, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_STABILIZED6] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_PURPLE, .repeats = 1, }, + { .time_off = 100, .time_on = 100, .color = COLOR_PURPLE, .repeats = 1, }, + { .time_off = 500, .time_on = 100, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_AUTOTUNE] = { .repeats = -1, .steps = { + { .time_off = 800, .time_on = 200, .color = COLOR_BLUE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_GPS] = { .repeats = -1, .steps = { + { .time_off = 800, .time_on = 200, .color = COLOR_GREEN, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_RTH] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_GREEN, .repeats = 1, }, + { .time_off = 100, .time_on = 100, .color = COLOR_YELLOW, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_LAND] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_GREEN, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ARMED_FM_AUTO] = { .repeats = -1, .steps = { + { .time_off = 100, .time_on = 200, .color = COLOR_GREEN, .repeats = 2, }, + { .time_off = 500, .time_on = 200, .color = COLOR_GREEN, .repeats = 1, }, + }, }, + + [NOTIFY_SEQUENCE_ALM_WARN_GPS] = { .repeats = 2, .steps = { + { .time_off = 300, .time_on = 300, .color = COLOR_ORANGE, .repeats = 2, }, + { .time_off = 300, .time_on = 300, .color = COLOR_GREEN, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ALM_ERROR_GPS] = { .repeats = 2, .steps = { + { .time_off = 300, .time_on = 300, .color = COLOR_RED, .repeats = 2, }, + { .time_off = 300, .time_on = 300, .color = COLOR_GREEN, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ALM_WARN_BATTERY] = { .repeats = 1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_ORANGE, .repeats = 10, }, + }, }, + [NOTIFY_SEQUENCE_ALM_ERROR_BATTERY] = { .repeats = 1, .steps = { + { .time_off = 100, .time_on = 100, .color = COLOR_RED, .repeats = 10, }, + }, }, + [NOTIFY_SEQUENCE_ALM_MAG] = { .repeats = 1, .steps = { + { .time_off = 300, .time_on = 300, .color = COLOR_RED, .repeats = 2, }, + { .time_off = 300, .time_on = 300, .color = COLOR_PURPLE, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ALM_CONFIG] = { .repeats = 1, .steps = { + { .time_off = 50, .time_on = 50, .color = COLOR_RED, .repeats = 9, }, + { .time_off = 500, .time_on = 50, .color = COLOR_RED, .repeats = 1, }, + }, }, + [NOTIFY_SEQUENCE_ALM_RECEIVER] = { .repeats = 1, .steps = { + { .time_off = 50, .time_on = 50, .color = COLOR_ORANGE, .repeats = 9, }, + { .time_off = 500, .time_on = 50, .color = COLOR_ORANGE, .repeats = 1, }, + }, }, +}; + +// List of background sequences attached to each flight mode +const LedSequence_t *flightModeMap[] = { + [FLIGHTSTATUS_FLIGHTMODE_MANUAL] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_MANUAL], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED1] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED1], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED2] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED2], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED3] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED3], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED4] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED4], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED5] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED5], + [FLIGHTSTATUS_FLIGHTMODE_STABILIZED6] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_STABILIZED6], + [FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_AUTO], + [FLIGHTSTATUS_FLIGHTMODE_AUTOTUNE] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_AUTOTUNE], + [FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], + [FLIGHTSTATUS_FLIGHTMODE_POSITIONVARIOFPV] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], + [FLIGHTSTATUS_FLIGHTMODE_POSITIONVARIOLOS] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], + [FLIGHTSTATUS_FLIGHTMODE_POSITIONVARIONSEW] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], + [FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_RTH], + [FLIGHTSTATUS_FLIGHTMODE_LAND] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_LAND], + [FLIGHTSTATUS_FLIGHTMODE_POI] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], + [FLIGHTSTATUS_FLIGHTMODE_AUTOCRUISE] = ¬ifications[NOTIFY_SEQUENCE_ARMED_FM_GPS], +}; + +// List of alarms to show with attached sequences for each status +const AlarmDefinition_t alarmsMap[] = { + { + .timeBetweenNotifications = 10000, + .alarmIndex = SYSTEMALARMS_ALARM_GPS, + .warnNotification = NOTIFY_SEQUENCE_ALM_WARN_GPS, + .errorNotification = NOTIFY_SEQUENCE_ALM_ERROR_GPS, + }, + { + .timeBetweenNotifications = 15000, + .alarmIndex = SYSTEMALARMS_ALARM_MAGNETOMETER, + .warnNotification = NOTIFY_SEQUENCE_NULL, + .errorNotification = NOTIFY_SEQUENCE_ALM_MAG, + }, + { + .timeBetweenNotifications = 15000, + .alarmIndex = SYSTEMALARMS_ALARM_BATTERY, + .warnNotification = NOTIFY_SEQUENCE_ALM_WARN_BATTERY, + .errorNotification = NOTIFY_SEQUENCE_ALM_ERROR_BATTERY, + }, + { + .timeBetweenNotifications = 5000, + .alarmIndex = SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, + .warnNotification = NOTIFY_SEQUENCE_NULL, + .errorNotification = NOTIFY_SEQUENCE_ALM_CONFIG, + }, + { + .timeBetweenNotifications = 5000, + .alarmIndex = SYSTEMALARMS_ALARM_RECEIVER, + .warnNotification = NOTIFY_SEQUENCE_ALM_RECEIVER, + .errorNotification = NOTIFY_SEQUENCE_ALM_RECEIVER, + }, +}; + +const uint8_t alarmsMapSize = NELEMENTS(alarmsMap); + +#endif /* SEQUENCES_H_ */ diff --git a/flight/modules/Notify/notify.c b/flight/modules/Notify/notify.c new file mode 100644 index 000000000..aeb7526bf --- /dev/null +++ b/flight/modules/Notify/notify.c @@ -0,0 +1,136 @@ +/** + ****************************************************************************** + * + * @file notify.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Notify module, show events and status on external led. + * + * @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 "openpilot.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inc/notify.h" +#include "inc/sequences.h" +#include +#include + +#define SAMPLE_PERIOD_MS 250 +// private types +typedef struct { + uint32_t lastAlarmTime; + uint8_t lastAlarm; +} AlarmStatus_t; +// function declarations +static void updatedCb(UAVObjEvent *ev); +static void onTimerCb(UAVObjEvent *ev); +static void checkAlarm(uint8_t alarm, uint8_t *last_alarm, uint32_t *last_alm_time, + uint8_t warn_sequence, uint8_t error_sequence, + uint32_t timeBetweenNotifications); +static AlarmStatus_t *alarmStatus; +int32_t NotifyInitialize(void) +{ + uint8_t ws281xOutStatus; + + HwSettingsWS2811LED_OutGet(&ws281xOutStatus); + // Todo: Until further applications exists for WS2811 notify enabled status is tied to ws281x output configuration + bool enabled = ws281xOutStatus != HWSETTINGS_WS2811LED_OUT_DISABLED; + + if (enabled) { + alarmStatus = (AlarmStatus_t *)pios_malloc(sizeof(AlarmStatus_t) * alarmsMapSize); + for (uint8_t i = 0; i < alarmsMapSize; i++) { + alarmStatus[i].lastAlarm = SYSTEMALARMS_ALARM_OK; + alarmStatus[i].lastAlarmTime = 0; + } + + FlightStatusConnectCallback(&updatedCb); + static UAVObjEvent ev; + memset(&ev, 0, sizeof(UAVObjEvent)); + EventPeriodicCallbackCreate(&ev, onTimerCb, SAMPLE_PERIOD_MS / portTICK_RATE_MS); + + updatedCb(0); + } + return 0; +} +MODULE_INITCALL(NotifyInitialize, 0); + + +void updatedCb(UAVObjEvent *ev) +{ + if (!ev || ev->obj == FlightStatusHandle()) { + static uint8_t last_armed = 0xff; + static uint8_t last_flightmode = 0xff; + uint8_t armed; + uint8_t flightmode; + FlightStatusArmedGet(&armed); + FlightStatusFlightModeGet(&flightmode); + if (last_armed != armed || (armed && flightmode != last_flightmode)) { + if (armed) { + PIOS_NOTIFICATION_Default_Ext_Led_Play(flightModeMap[flightmode], NOTIFY_PRIORITY_BACKGROUND); + } else { + PIOS_NOTIFICATION_Default_Ext_Led_Play(¬ifications[NOTIFY_SEQUENCE_DISARMED], NOTIFY_PRIORITY_BACKGROUND); + } + } + last_armed = armed; + last_flightmode = flightmode; + } +} + +void onTimerCb(__attribute__((unused)) UAVObjEvent *ev) +{ + static SystemAlarmsAlarmData alarms; + + SystemAlarmsAlarmGet(&alarms); + for (uint8_t i = 0; i < alarmsMapSize; i++) { + uint8_t alarm = ((uint8_t *)&alarms)[alarmsMap[i].alarmIndex]; + checkAlarm(alarm, + &alarmStatus[i].lastAlarm, + &alarmStatus[i].lastAlarmTime, + alarmsMap[i].warnNotification, + alarmsMap[i].errorNotification, + alarmsMap[i].timeBetweenNotifications); + } +} + +void checkAlarm(uint8_t alarm, uint8_t *last_alarm, uint32_t *last_alm_time, uint8_t warn_sequence, uint8_t error_sequence, uint32_t timeBetweenNotifications) +{ + if (alarm > SYSTEMALARMS_ALARM_OK) { + uint32_t current_time = PIOS_DELAY_GetuS(); + if (*last_alarm < alarm || *last_alm_time + timeBetweenNotifications * 1000 < current_time) { + uint8_t sequence = (alarm == SYSTEMALARMS_ALARM_WARNING) ? warn_sequence : error_sequence; + if (sequence != NOTIFY_SEQUENCE_NULL) { + PIOS_NOTIFICATION_Default_Ext_Led_Play( + ¬ifications[sequence], + alarm == SYSTEMALARMS_ALARM_WARNING ? NOTIFY_PRIORITY_REGULAR : NOTIFY_PRIORITY_CRITICAL); + } + *last_alarm = alarm; + *last_alm_time = current_time; + } + } else { + *last_alarm = SYSTEMALARMS_ALARM_OK; + } +} diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index 97ff55f3d..affcf580d 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -41,7 +41,11 @@ #include // private includes #include "inc/systemmod.h" -#include "notification.h" + +#include +#ifdef PIOS_INCLUDE_WS2811 +#include +#endif // UAVOs #include @@ -54,6 +58,7 @@ #include #include #include +#include #ifdef PIOS_INCLUDE_INSTRUMENTATION #include @@ -632,6 +637,9 @@ static void updateSystemAlarms() void vApplicationIdleHook(void) { NotificationOnboardLedsRun(); +#ifdef PIOS_INCLUDE_WS2811 + LedNotificationExtLedsRun(); +#endif } /** * Called by the RTOS when a stack overflow is detected. diff --git a/flight/pios/common/pios_notify.c b/flight/pios/common/pios_notify.c index bf83c22eb..9b0a1fc67 100644 --- a/flight/pios/common/pios_notify.c +++ b/flight/pios/common/pios_notify.c @@ -28,7 +28,8 @@ static volatile pios_notify_notification currentNotification = NOTIFY_NONE; static volatile pios_notify_priority currentPriority; - +static volatile ExtLedNotification_t extLedNotification; +static volatile bool newNotification; void PIOS_NOTIFY_StartNotification(pios_notify_notification notification, pios_notify_priority priority) { @@ -47,3 +48,36 @@ pios_notify_notification PIOS_NOTIFY_GetActiveNotification(bool clear) } return ret; } + + +/* + * Play a sequence on the default external led. Sequences with priority higher than NOTIFY_PRIORITY_LOW + * are repeated only once if repeat = -1 + * @param sequence Sequence to be played + * @param priority Priority of the sequence being played + */ +void PIOS_NOTIFICATION_Default_Ext_Led_Play(const LedSequence_t *sequence, pios_notify_priority priority) +{ + // alert and alarms are repeated if condition persists. bacground notification instead are set once, so try to prevent loosing any update + if (newNotification && priority != NOTIFY_PRIORITY_BACKGROUND) { + // prevent overwriting higher priority or background notifications + if (extLedNotification.priority == NOTIFY_PRIORITY_BACKGROUND || extLedNotification.priority > priority) { + return; + } + } + extLedNotification.priority = priority; + extLedNotification.sequence = *sequence; + newNotification = true; +} + + +ExtLedNotification_t *PIOS_NOTIFY_GetNewExtLedSequence(bool clear) +{ + if (!newNotification) { + return 0; + } + if (clear) { + newNotification = false; + } + return (ExtLedNotification_t *)&extLedNotification; +} diff --git a/flight/pios/inc/pios_notify.h b/flight/pios/inc/pios_notify.h index 1e800df5c..12daefdc2 100644 --- a/flight/pios/inc/pios_notify.h +++ b/flight/pios/inc/pios_notify.h @@ -26,7 +26,7 @@ #ifndef PIOS_NOTIFY_H_ #define PIOS_NOTIFY_H_ #include - +#include typedef enum { NOTIFY_NONE = 0, NOTIFY_OK, @@ -35,11 +35,35 @@ typedef enum { } pios_notify_notification; typedef enum { - NOTIFY_PRIORITY_CRITICAL = 2, - NOTIFY_PRIORITY_REGULAR = 1, + NOTIFY_PRIORITY_CRITICAL = 2, + NOTIFY_PRIORITY_REGULAR = 1, NOTIFY_PRIORITY_LOW = 0, + NOTIFY_PRIORITY_BACKGROUND = -1, } pios_notify_priority; + +// A single led step, Color, time On/Off, repeat count +#define NOTIFY_SEQUENCE_MAX_STEPS 5 + +typedef struct { + uint16_t time_off; + uint16_t time_on; + Color_t color; + uint8_t repeats; +} LedStep_t; + +typedef struct { + int8_t repeats; // -1 for infinite repetitions + LedStep_t steps[NOTIFY_SEQUENCE_MAX_STEPS]; +} LedSequence_t; + +typedef struct { + LedSequence_t sequence; + pios_notify_priority priority; +} ExtLedNotification_t; + +#define NOTIFY_IS_NULL_STEP(x) (!x || (!x->time_off && !x->time_on && !x->repeats)) + /** * 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 @@ -55,4 +79,24 @@ void PIOS_NOTIFY_StartNotification(pios_notify_notification notification, pios_n */ pios_notify_notification PIOS_NOTIFY_GetActiveNotification(bool clear); +/* + * Play a sequence on the default external led. Sequences with priority higher than NOTIFY_PRIORITY_LOW + * are repeated only once if repeat = -1 + * @param sequence Sequence to be played + * @param priority Priority of the sequence being played + */ +void PIOS_NOTIFICATION_Default_Ext_Led_Play(const LedSequence_t *sequence, pios_notify_priority priority); + +/* + * Play a sequence on an external rgb led. Sequences with priority higher than NOTIFY_PRIORITY_LOW + * are repeated only once if repeat = -1 + * @param sequence Sequence to be played + * @param ledNumber Led number + * @param priority Priority of the sequence being played + * + */ +// void PIOS_NOTIFICATION_Ext_Led_Play(const LedSequence_t sequence, uint8_t ledNumber, pios_notify_priority priority); + +ExtLedNotification_t *PIOS_NOTIFY_GetNewExtLedSequence(bool clear); + #endif /* PIOS_NOTIFY_H_ */ diff --git a/flight/pios/inc/pios_ws2811.h b/flight/pios/inc/pios_ws2811.h index cb05070ee..2d04288a2 100644 --- a/flight/pios/inc/pios_ws2811.h +++ b/flight/pios/inc/pios_ws2811.h @@ -29,119 +29,11 @@ #define PIOS_WS2811_H_ #include -#include -#include -#include -#include -#include -#include +#include +#define PIOS_WS2811_NUMLEDS 2 -#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 - -// 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, \ - .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, } - -#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_VeryHigh, } - -#define PIOS_WS2811_DMA_UPDATE_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 } - - -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_setColorRGB(Color_t 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/inc/pios_ws2811_cfg.h b/flight/pios/inc/pios_ws2811_cfg.h new file mode 100644 index 000000000..a4a6b5739 --- /dev/null +++ b/flight/pios/inc/pios_ws2811_cfg.h @@ -0,0 +1,136 @@ +/** + ****************************************************************************** + * + * @file pios_ws2811_cfg.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_CFG_H_ +#define PIOS_WS2811_CFG_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +// Following times are keept on the lower side to accounts +// for bus contentions and irq response time +#define PIOS_WS2811_T0_HIGH_PERIOD 32 // .35us +/- 150nS +#define PIOS_WS2811_T1_HIGH_PERIOD 70 // .70us +/- 150nS + +#define PIOS_WS2811_DMA_CH1_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, } + +#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_VeryHigh, } + +#define PIOS_WS2811_DMA_UPDATE_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 } + + +typedef uint16_t ledbuf_t; + +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_DMA_irq_handler(); +#endif /* PIOS_WS2811_H_ */ diff --git a/flight/pios/stm32f4xx/pios_ws2811.c b/flight/pios/stm32f4xx/pios_ws2811.c index 96719a4a8..4b8e9d987 100644 --- a/flight/pios/stm32f4xx/pios_ws2811.c +++ b/flight/pios/stm32f4xx/pios_ws2811.c @@ -29,7 +29,7 @@ #ifdef PIOS_INCLUDE_WS2811 -#include "pios_ws2811.h" +#include "pios_ws2811_cfg.h" #include #include #include "FreeRTOS.h" @@ -177,7 +177,7 @@ void PIOS_WS2811_Init(const struct pios_ws2811_cfg *ws2811_cfg, const struct pio fb = (ledbuf_t *)pios_malloc(PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); memset(fb, 0, PIOS_WS2811_BUFFER_SIZE * sizeof(ledbuf_t)); - Color ledoff = { 0, 0, 0 }; + const Color_t ledoff = Color_Off; for (uint8_t i = 0; i < PIOS_WS2811_NUMLEDS; i++) { PIOS_WS2811_setColorRGB(ledoff, i, false); } @@ -302,7 +302,7 @@ 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) +void PIOS_WS2811_setColorRGB(Color_t c, uint8_t led, bool update) { if (led >= PIOS_WS2811_NUMLEDS) { return; @@ -310,6 +310,7 @@ void PIOS_WS2811_setColorRGB(Color c, uint8_t led, bool update) 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(); } @@ -327,6 +328,10 @@ void PIOS_WS2811_Update() // reset counters for synchronization pios_ws2811_cfg->timer->CNT = PIOS_WS2811_TIM_PERIOD - 1; + + DMA_Cmd(pios_ws2811_cfg->streamCh2, ENABLE); + DMA_Cmd(pios_ws2811_cfg->streamCh1, ENABLE); + DMA_Cmd(pios_ws2811_cfg->streamUpdate, ENABLE); // Start a new cycle TIM_Cmd(pios_ws2811_cfg->timer, ENABLE); } @@ -337,8 +342,12 @@ void PIOS_WS2811_Update() void PIOS_WS2811_DMA_irq_handler() { + pios_ws2811_pin_cfg->gpio->BSRRH = dmaSource[0]; pios_ws2811_cfg->timer->CR1 &= (uint16_t) ~TIM_CR1_CEN; DMA_ClearFlag(pios_ws2811_cfg->streamCh1, pios_ws2811_cfg->irq.flags); + DMA_Cmd(pios_ws2811_cfg->streamCh2, DISABLE); + DMA_Cmd(pios_ws2811_cfg->streamCh1, DISABLE); + DMA_Cmd(pios_ws2811_cfg->streamUpdate, DISABLE); } #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 4583fe6b4..097a8e193 100644 --- a/flight/targets/boards/discoveryf4bare/board_hw_defs.c +++ b/flight/targets/boards/discoveryf4bare/board_hw_defs.c @@ -1811,7 +1811,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 +#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"))); diff --git a/flight/targets/boards/discoveryf4bare/firmware/Makefile b/flight/targets/boards/discoveryf4bare/firmware/Makefile index a8445af32..ca746d4a7 100644 --- a/flight/targets/boards/discoveryf4bare/firmware/Makefile +++ b/flight/targets/boards/discoveryf4bare/firmware/Makefile @@ -35,6 +35,7 @@ USE_DSP_LIB ?= NO #MODULES += Airspeed #MODULES += AltitudeHold MODULES += Stabilization +MODULES += Notify MODULES += ManualControl MODULES += Receiver MODULES += Actuator @@ -88,6 +89,7 @@ ifndef TESTAPP SRC += $(FLIGHTLIB)/WorldMagModel.c SRC += $(FLIGHTLIB)/insgps13state.c SRC += $(FLIGHTLIB)/auxmagsupport.c + SRC += $(FLIGHTLIB)/lednotification.c ## UAVObjects include ./UAVObjects.inc diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 98fce19c7..3a7cf115f 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -1964,7 +1964,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 +#include #include #define PIOS_WS2811_TIM_DIVIDER (PIOS_PERIPHERAL_APB2_CLOCK / (800000 * PIOS_WS2811_TIM_PERIOD)) diff --git a/flight/targets/boards/revolution/firmware/Makefile b/flight/targets/boards/revolution/firmware/Makefile index 21b23ed68..462cdb166 100644 --- a/flight/targets/boards/revolution/firmware/Makefile +++ b/flight/targets/boards/revolution/firmware/Makefile @@ -49,6 +49,7 @@ MODULES += PathFollower MODULES += Osd/osdoutout MODULES += Logging MODULES += Telemetry +MODULES += Notify OPTMODULES += ComUsbBridge @@ -88,6 +89,7 @@ ifndef TESTAPP SRC += $(FLIGHTLIB)/WorldMagModel.c SRC += $(FLIGHTLIB)/insgps13state.c SRC += $(FLIGHTLIB)/auxmagsupport.c + SRC += $(FLIGHTLIB)/lednotification.c ## UAVObjects include ./UAVObjects.inc diff --git a/flight/tests/lednotification/FreeRTOS.h b/flight/tests/lednotification/FreeRTOS.h new file mode 100644 index 000000000..c8b49f26d --- /dev/null +++ b/flight/tests/lednotification/FreeRTOS.h @@ -0,0 +1 @@ +#include diff --git a/flight/tests/lednotification/Makefile b/flight/tests/lednotification/Makefile new file mode 100644 index 000000000..d013f5b83 --- /dev/null +++ b/flight/tests/lednotification/Makefile @@ -0,0 +1,41 @@ +############################################################################### +# @file Makefile +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# Copyright (c) 2013, The OpenPilot Team, http://www.openpilot.org +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile for unit test +############################################################################### +# +# 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 OPENPILOT_IS_COOL + $(error Top level Makefile must be used to build this target) +endif + +include $(ROOT_DIR)/make/firmware-defs.mk + +EXTRAINCDIRS += $(TOPDIR) +EXTRAINCDIRS += $(PIOS)/inc +EXTRAINCDIRS += $(FLIGHTLIB)/inc +EXTRAINCDIRS += $(FLIGHTLIB) + +SRC += $(FLIGHTLIB)/optypes.c +SRC += $(PIOS)/common/pios_notify.c + +include $(ROOT_DIR)/make/unittest.mk diff --git a/flight/tests/lednotification/openpilot.h b/flight/tests/lednotification/openpilot.h new file mode 100644 index 000000000..4c2259d19 --- /dev/null +++ b/flight/tests/lednotification/openpilot.h @@ -0,0 +1,11 @@ +#ifndef OPENPILOT_H +#define OPENPILOT_H + +#include + +#define PIOS_Assert(x) \ + if (!(x)) { while (1) {; } \ + } +#define PIOS_DEBUG_Assert(x) PIOS_Assert(x) + +#endif /* OPENPILOT_H */ diff --git a/flight/tests/lednotification/pios.h b/flight/tests/lednotification/pios.h new file mode 100644 index 000000000..12cd5e76a --- /dev/null +++ b/flight/tests/lednotification/pios.h @@ -0,0 +1,13 @@ +#ifndef PIOS_H +#define PIOS_H + +/* PIOS Feature Selection */ +#include "pios_config.h" + +#ifdef PIOS_INCLUDE_FREERTOS +/* FreeRTOS Includes */ +#include "FreeRTOS.h" +#endif +#include "pios_mem.h" + +#endif /* PIOS_H */ diff --git a/flight/tests/lednotification/pios_config.h b/flight/tests/lednotification/pios_config.h new file mode 100644 index 000000000..2a645e951 --- /dev/null +++ b/flight/tests/lednotification/pios_config.h @@ -0,0 +1,6 @@ +#ifndef PIOS_CONFIG_H +#define PIOS_CONFIG_H + +#define PIOS_INCLUDE_FREERTOS + +#endif /* PIOS_CONFIG_H */ diff --git a/flight/tests/lednotification/pios_mem.h b/flight/tests/lednotification/pios_mem.h new file mode 100644 index 000000000..279ce5aef --- /dev/null +++ b/flight/tests/lednotification/pios_mem.h @@ -0,0 +1,34 @@ +/** + ****************************************************************************** + * + * @file pios_mem.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. + * @addtogroup PiOS + * @{ + * @addtogroup PiOS + * @{ + * @brief PiOS memory allocation API + *****************************************************************************/ +/* + * 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_MEM_H +#define PIOS_MEM_H + +#define pios_fastheapmalloc(size) (malloc(size)) +#define pios_malloc(size) (malloc(size)) +#define pios_free(p) (free(p)) + +#endif /* PIOS_MEM_H */ diff --git a/flight/tests/lednotification/unittest.cpp b/flight/tests/lednotification/unittest.cpp new file mode 100644 index 000000000..853d4b9f8 --- /dev/null +++ b/flight/tests/lednotification/unittest.cpp @@ -0,0 +1,153 @@ +#include "gtest/gtest.h" + +#include /* printf */ +#include /* abort */ +#include /* memset */ + +extern "C" { +#define xTaskGetTickCount() 1 +#define portTICK_RATE_MS 1 + +#include "lednotification.c" + +void PIOS_WS2811_setColorRGB(__attribute__((unused)) Color_t c, __attribute__((unused)) uint8_t led, __attribute__((unused)) bool update) {} +void PIOS_WS2811_Update() {} +} + +class LedNotificationTest : public testing::Test {}; + +int compare_int8(const void *a, const void *b) +{ + const int8_t *da = (const int8_t *)a; + const int8_t *db = (const int8_t *)b; + + return (*da > *db) - (*da < *db); +} + + +void sort_priorities(int8_t *queued_priorities) +{ + qsort(queued_priorities, MAX_BACKGROUND_NOTIFICATIONS, sizeof(int8_t), compare_int8); +} + +void set_highest_active(NotifierLedStatus_t *status) +{ + int8_t highest = NOTIFY_PRIORITY_BACKGROUND; + + for (int i = 0; i < MAX_BACKGROUND_NOTIFICATIONS; i++) { + if (status->queued_priorities[i] > highest) { + status->active_sequence_num = i; + highest = status->queued_priorities[i]; + } + } +} + +void insert(NotifierLedStatus_t *status, pios_notify_priority priority) +{ + ExtLedNotification_t notification; + + notification.priority = priority; + push_queued_sequence(¬ification, status); +} + +void init(NotifierLedStatus_t *status, pios_notify_priority priority) +{ + for (uint8_t i = 0; i < MAX_BACKGROUND_NOTIFICATIONS; i++) { + status->queued_priorities[i] = priority; + } +} + +TEST_F(LedNotificationTest, TestQueueOrder1) { + NotifierLedStatus_t status; + + init(&status, NOTIFY_PRIORITY_BACKGROUND); + + insert(&status, NOTIFY_PRIORITY_LOW); + insert(&status, NOTIFY_PRIORITY_CRITICAL); + insert(&status, NOTIFY_PRIORITY_LOW); + insert(&status, NOTIFY_PRIORITY_CRITICAL); + + set_highest_active(&status); + + + EXPECT_EQ(NOTIFY_PRIORITY_CRITICAL, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_CRITICAL, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_BACKGROUND, (status.queued_priorities[status.active_sequence_num])); +} + +TEST_F(LedNotificationTest, TestQueueOrder2) { + NotifierLedStatus_t status; + +// Fails because insert_point and first_point will both be -1. This will also cause an array-out-of bounds at: +// 146 status->queued_priorities[insert_point] = new_notification->priority; +// 147 status->queued_sequences[insert_point] = new_notification->sequence; +// 148 updated_sequence = insert_point; + + init(&status, NOTIFY_PRIORITY_LOW); + status.queued_priorities[0] = NOTIFY_PRIORITY_BACKGROUND; + + insert(&status, NOTIFY_PRIORITY_REGULAR); + + set_highest_active(&status); + + EXPECT_EQ(NOTIFY_PRIORITY_REGULAR, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_BACKGROUND, (status.queued_priorities[status.active_sequence_num])); +} + +TEST_F(LedNotificationTest, TestQueueOrder3) { + NotifierLedStatus_t status; + + // Fails because queued_priorities[0] _LOW and not _REGULAR. I _thibnk_ this is a bug. + init(&status, NOTIFY_PRIORITY_REGULAR); + status.queued_priorities[0] = NOTIFY_PRIORITY_BACKGROUND; + + insert(&status, NOTIFY_PRIORITY_LOW); + + set_highest_active(&status); + + + for (uint8_t i = 0; i < MAX_BACKGROUND_NOTIFICATIONS - 1; i++) { + EXPECT_EQ(NOTIFY_PRIORITY_REGULAR, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + } +} + +TEST_F(LedNotificationTest, TestQueueOrder4) { + NotifierLedStatus_t status; + + init(&status, NOTIFY_PRIORITY_BACKGROUND); + + insert(&status, NOTIFY_PRIORITY_REGULAR); + insert(&status, NOTIFY_PRIORITY_REGULAR); + insert(&status, NOTIFY_PRIORITY_REGULAR); + insert(&status, NOTIFY_PRIORITY_LOW); + + set_highest_active(&status); + + EXPECT_EQ(NOTIFY_PRIORITY_REGULAR, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_REGULAR, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_REGULAR, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_LOW, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_BACKGROUND, (status.queued_priorities[status.active_sequence_num])); + pop_queued_sequence(&status); + EXPECT_EQ(NOTIFY_PRIORITY_BACKGROUND, (status.queued_priorities[status.active_sequence_num])); +} diff --git a/ground/openpilotgcs/src/plugins/config/images/fixedwing-shapes.svg b/ground/openpilotgcs/src/plugins/config/images/fixedwing-shapes.svg index 9b5a425b0..952b65bee 100644 --- a/ground/openpilotgcs/src/plugins/config/images/fixedwing-shapes.svg +++ b/ground/openpilotgcs/src/plugins/config/images/fixedwing-shapes.svg @@ -487,16 +487,20 @@ inkscape:window-height="928" id="namedview4099" showgrid="false" - inkscape:zoom="0.73144533" - inkscape:cx="784.15573" - inkscape:cy="958.96697" + inkscape:zoom="4.0911178" + inkscape:cx="396.11045" + inkscape:cy="611.35183" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" - inkscape:current-layer="elevon" + inkscape:current-layer="Layer_1" showborder="true" inkscape:showpageshadow="false" - inkscape:object-paths="true" /> \ No newline at end of file + style="fill:none;stroke:#010101;stroke-width:0.69520003;stroke-linecap:round;stroke-linejoin:round" /> \ No newline at end of file diff --git a/ground/openpilotgcs/src/plugins/config/images/ground-shapes.svg b/ground/openpilotgcs/src/plugins/config/images/ground-shapes.svg index b01fec06e..ee8cd7410 100644 --- a/ground/openpilotgcs/src/plugins/config/images/ground-shapes.svg +++ b/ground/openpilotgcs/src/plugins/config/images/ground-shapes.svg @@ -20,7 +20,7 @@ enable-background="new 0 0 792 1008" xml:space="preserve" inkscape:version="0.48.5 r10040" - sodipodi:docname="ground-shapes-wizard.svg" + sodipodi:docname="ground-shapes.svg.2014_09_18_19_55_33.0.svg" inkscape:export-filename="/home/laurent/Images/car.png" inkscape:export-xdpi="70.479134" inkscape:export-ydpi="70.479134"> \ No newline at end of file + d="M 164.97807,1032.3266 C 132.36283,1032.3266 105.93071,1058.7587 105.93071,1091.374 C 105.93071,1123.9892 132.36283,1150.4214 164.97807,1150.4214 L 523.74691,1150.8947 C 556.36217,1150.8947 582.79428,1124.4627 582.79428,1091.8473 C 582.79428,1059.2321 556.36217,1032.7999 523.74691,1032.7999 L 164.97807,1032.3266 z M 165.12756,1038.5054 L 523.59742,1038.9289 C 552.80971,1038.9289 576.49091,1062.6101 576.49091,1091.8224 C 576.49091,1121.0348 552.80971,1144.7159 523.59742,1144.7159 L 165.12756,1144.2924 C 135.91528,1144.2924 112.23408,1120.6112 112.23408,1091.3989 C 112.23408,1062.1866 135.91528,1038.5054 165.12756,1038.5054 z" + style="opacity:0.95864659;color:#000000;fill:#4e93f6;fill-opacity:1;fill-rule:nonzero;stroke:#131715;stroke-width:0.36675274;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> \ No newline at end of file diff --git a/ground/openpilotgcs/src/plugins/config/output.ui b/ground/openpilotgcs/src/plugins/config/output.ui index 575b03e58..a09aa8f88 100644 --- a/ground/openpilotgcs/src/plugins/config/output.ui +++ b/ground/openpilotgcs/src/plugins/config/output.ui @@ -282,8 +282,8 @@ - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -320,6 +320,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + @@ -340,8 +345,8 @@ Leave at 50Hz for fixed wing. - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -378,6 +383,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + @@ -420,8 +430,8 @@ Leave at 50Hz for fixed wing. - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -458,6 +468,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + @@ -478,8 +493,8 @@ Leave at 50Hz for fixed wing. - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -516,6 +531,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + @@ -546,8 +566,8 @@ Leave at 50Hz for fixed wing. - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -584,6 +604,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + @@ -604,8 +629,8 @@ Leave at 50Hz for fixed wing. - Setup "TurboPWM" here: usual value is 400 Hz for multirotor airframes. -Leave at 50Hz for fixed wing. + Setup "RapidESC" here: usual value is 500 Hz for multirotor airframes. + @@ -642,6 +667,11 @@ Leave at 50Hz for fixed wing. 400 + + + 500 + + diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/escpage.ui b/ground/openpilotgcs/src/plugins/setupwizard/pages/escpage.ui index c06ca1d7d..a086e0f84 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/escpage.ui +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/escpage.ui @@ -26,8 +26,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To set an optimal configuration of the output signals powering your motors, the wizard needs to know what type of Electronic Speed Controllers (ESCs) you will use and what their capabilities are.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Please select one of the options below. If you are unsure about the capabilities of your ESCs, just leave the default option selected and continue the wizard.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To read more regarding ESC refresh rates, please see </span><a href="http://wiki.openpilot.org/x/HIEu"><span style=" font-family:'Lucida Grande'; font-size:13pt; text-decoration: underline; color:#0000ff;">this article</span></a><span style=" font-size:10pt;"> in the OpenPilot Wiki</span></p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -113,12 +112,12 @@ p, li { white-space: pre-wrap; } QToolButton { border: none } - Turbo PWM + Rapid ESC - :/setupwizard/resources/bttn-turbo-up.png - :/setupwizard/resources/bttn-turbo-down.png:/setupwizard/resources/bttn-turbo-up.png + :/setupwizard/resources/bttn-rapid-up.png + :/setupwizard/resources/bttn-rapid-dwn.png:/setupwizard/resources/bttn-rapid-up.png diff --git a/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-dwn.png b/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-dwn.png new file mode 100644 index 000000000..04d5eb559 Binary files /dev/null and b/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-dwn.png differ diff --git a/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-up.png b/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-up.png new file mode 100644 index 000000000..72ffa2cc7 Binary files /dev/null and b/ground/openpilotgcs/src/plugins/setupwizard/resources/bttn-rapid-up.png differ diff --git a/ground/openpilotgcs/src/plugins/setupwizard/resources/connection-diagrams.svg b/ground/openpilotgcs/src/plugins/setupwizard/resources/connection-diagrams.svg index fefc1c59a..6e42f8ac6 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/resources/connection-diagrams.svg +++ b/ground/openpilotgcs/src/plugins/setupwizard/resources/connection-diagrams.svg @@ -12,8 +12,8 @@ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg12651" - height="839.08447" - width="1309.343" + height="1074.8231" + width="1398.5884" version="1.1" inkscape:version="0.48.5 r10040" sodipodi:docname="connection-diagrams.svg"> @@ -26,17 +26,17 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="593" - inkscape:window-height="439" + inkscape:window-width="1280" + inkscape:window-height="928" id="namedview4616" showgrid="false" - inkscape:zoom="0.1891554" - inkscape:cx="1013.827" - inkscape:cy="514.92134" - inkscape:window-x="331" - inkscape:window-y="337" - inkscape:window-maximized="0" - inkscape:current-layer="layer7" + inkscape:zoom="0.67825113" + inkscape:cx="942.97766" + inkscape:cy="537.41156" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer20" fit-margin-top="15" fit-margin-left="15" fit-margin-right="15" @@ -48,38 +48,39 @@ inkscape:snap-bbox="true" inkscape:object-paths="true" inkscape:snap-bbox-midpoints="true" - inkscape:snap-bbox-edge-midpoints="true"> + inkscape:snap-bbox-edge-midpoints="true" + inkscape:object-nodes="true"> + originx="-32.46875px" + originy="239.45435px" /> @@ -103,7 +104,7 @@ @@ -117,7 +118,7 @@ @@ -144,7 +145,7 @@ style="overflow:visible"> @@ -158,7 +159,7 @@ style="overflow:visible"> @@ -180,7 +181,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10057"> @@ -188,7 +189,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10073"> @@ -220,7 +221,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10105"> @@ -249,7 +250,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10165"> @@ -257,7 +258,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10181"> @@ -273,7 +274,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10213"> @@ -289,7 +290,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10269"> @@ -297,7 +298,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10285"> @@ -313,7 +314,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10317"> @@ -329,7 +330,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4329"> @@ -337,7 +338,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4345"> @@ -353,7 +354,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4377"> @@ -385,7 +386,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4437"> @@ -393,7 +394,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4453"> @@ -409,7 +410,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4485"> @@ -433,7 +434,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4925"> @@ -441,7 +442,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4941"> @@ -457,7 +458,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4973"> @@ -486,7 +487,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7903"> @@ -494,7 +495,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7919"> @@ -510,7 +511,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7951"> @@ -539,7 +540,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5467"> @@ -547,7 +548,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5483"> @@ -555,7 +556,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5499"> @@ -563,7 +564,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5515"> @@ -571,7 +572,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5553"> @@ -587,7 +588,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5585"> @@ -603,7 +604,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5617"> @@ -619,7 +620,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5649"> @@ -635,7 +636,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5681"> @@ -651,7 +652,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5713"> @@ -667,7 +668,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5745"> @@ -683,7 +684,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5777"> @@ -712,7 +713,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7159"> @@ -720,7 +721,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7175"> @@ -736,7 +737,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7207"> @@ -752,7 +753,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7239"> @@ -760,7 +761,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7255"> @@ -776,7 +777,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7287"> @@ -792,7 +793,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7319"> @@ -800,7 +801,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7335"> @@ -816,7 +817,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7367"> @@ -832,7 +833,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7423"> @@ -840,7 +841,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7439"> @@ -856,7 +857,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7471"> @@ -872,7 +873,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7503"> @@ -880,7 +881,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7519"> @@ -896,7 +897,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7551"> @@ -912,7 +913,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7583"> @@ -920,7 +921,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7599"> @@ -936,7 +937,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7631"> @@ -965,7 +966,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5841"> @@ -973,7 +974,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5857"> @@ -981,7 +982,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5873"> @@ -989,7 +990,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5889"> @@ -997,7 +998,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5905"> @@ -1013,7 +1014,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5937"> @@ -1029,7 +1030,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5969"> @@ -1045,7 +1046,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6001"> @@ -1061,7 +1062,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6033"> @@ -1077,7 +1078,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6065"> @@ -1093,7 +1094,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6097"> @@ -1109,7 +1110,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6129"> @@ -1125,7 +1126,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6169"> @@ -1133,7 +1134,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6185"> @@ -1149,7 +1150,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6217"> @@ -1165,7 +1166,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6273"> @@ -1173,7 +1174,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6289"> @@ -1189,7 +1190,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6321"> @@ -1218,7 +1219,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5049"> @@ -1226,7 +1227,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5065"> @@ -1234,7 +1235,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5081"> @@ -1242,7 +1243,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5097"> @@ -1250,7 +1251,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5135"> @@ -1266,7 +1267,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5167"> @@ -1282,7 +1283,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5199"> @@ -1298,7 +1299,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5231"> @@ -1314,7 +1315,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5263"> @@ -1330,7 +1331,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5295"> @@ -1354,7 +1355,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5327"> @@ -1362,7 +1363,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5359"> @@ -1705,7 +1706,7 @@ @@ -1720,7 +1721,7 @@ inkscape:connector-curvature="0" id="path6056-4" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -1748,7 +1749,7 @@ inkscape:connector-curvature="0" id="path21212" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -1776,7 +1777,7 @@ inkscape:connector-curvature="0" id="path21220" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -1910,7 +1911,7 @@ inkscape:connector-curvature="0" id="path6056-7" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -1938,7 +1939,7 @@ inkscape:connector-curvature="0" id="path11149" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -1966,7 +1967,7 @@ inkscape:connector-curvature="0" id="path11157" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2135,7 +2136,7 @@ inkscape:connector-curvature="0" id="path6056-0" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2163,7 +2164,7 @@ inkscape:connector-curvature="0" id="path11726" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2191,7 +2192,7 @@ inkscape:connector-curvature="0" id="path11734" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2219,7 +2220,7 @@ inkscape:connector-curvature="0" id="path21220-7" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2336,7 +2337,7 @@ inkscape:connector-curvature="0" id="path6056-77" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2364,7 +2365,7 @@ inkscape:connector-curvature="0" id="path12589" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2392,7 +2393,7 @@ inkscape:connector-curvature="0" id="path12597" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2420,7 +2421,7 @@ inkscape:connector-curvature="0" id="path12605" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2448,7 +2449,7 @@ inkscape:connector-curvature="0" id="path12613" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + d="M 8.7185878,4.0337352 L -2.2072895,0.01601326 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z" transform="matrix(-0.3,0,0,-0.3,0.69,0)" /> @@ -2565,7 +2566,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10073-9"> @@ -2598,7 +2599,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10105-5"> @@ -2650,7 +2651,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10165-8"> @@ -2658,7 +2659,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10181-4"> @@ -2691,7 +2692,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10213-1"> @@ -2724,7 +2725,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10269-1"> @@ -2732,7 +2733,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10285-2"> @@ -2765,7 +2766,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath10317-2"> @@ -2817,7 +2818,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5049-7"> @@ -2825,7 +2826,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5065-3"> @@ -2883,7 +2884,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5327-2"> @@ -3016,7 +3017,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5081-8"> @@ -3024,7 +3025,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5097-0"> @@ -3032,7 +3033,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5135-8"> @@ -3065,7 +3066,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5167-6"> @@ -3098,7 +3099,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5199-9"> @@ -3131,7 +3132,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5231-4"> @@ -3164,7 +3165,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5263-5"> @@ -3197,7 +3198,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5295-4"> @@ -3230,7 +3231,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5359-0"> @@ -3282,7 +3283,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5467-7"> @@ -3290,7 +3291,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5483-5"> @@ -3298,7 +3299,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5499-4"> @@ -3306,7 +3307,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5515-6"> @@ -3314,7 +3315,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5553-5"> @@ -3347,7 +3348,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5585-3"> @@ -3380,7 +3381,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5617-0"> @@ -3413,7 +3414,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5649-4"> @@ -3446,7 +3447,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5681-5"> @@ -3479,7 +3480,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5713-8"> @@ -3512,7 +3513,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5745-4"> @@ -3545,7 +3546,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5777-6"> @@ -3597,7 +3598,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5841-2"> @@ -3605,7 +3606,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5857-0"> @@ -3613,7 +3614,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5873-6"> @@ -3621,7 +3622,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5889-2"> @@ -3629,7 +3630,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5905-8"> @@ -3662,7 +3663,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5937-3"> @@ -3695,7 +3696,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5969-3"> @@ -3728,7 +3729,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6001-7"> @@ -3761,7 +3762,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6033-5"> @@ -3794,7 +3795,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6065-8"> @@ -3827,7 +3828,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6097-0"> @@ -3860,7 +3861,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6129-2"> @@ -3893,7 +3894,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6169-2"> @@ -3901,7 +3902,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6185-2"> @@ -3934,7 +3935,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6217-8"> @@ -3967,7 +3968,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6273-5"> @@ -3975,7 +3976,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6289-4"> @@ -4008,7 +4009,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6321-0"> @@ -4064,7 +4065,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7159-1"> @@ -4072,7 +4073,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7175-5"> @@ -4105,7 +4106,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7207-6"> @@ -4138,7 +4139,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7239-4"> @@ -4146,7 +4147,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7255-7"> @@ -4179,7 +4180,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7287-1"> @@ -4212,7 +4213,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7319-8"> @@ -4220,7 +4221,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7367-9"> @@ -4253,7 +4254,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7335-3"> @@ -4286,7 +4287,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7423-6"> @@ -4294,7 +4295,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7439-8"> @@ -4327,7 +4328,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7471-3"> @@ -4360,7 +4361,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7503-0"> @@ -4368,7 +4369,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7519-4"> @@ -4401,7 +4402,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7551-8"> @@ -4434,7 +4435,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7583-7"> @@ -4442,7 +4443,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7599-4"> @@ -4475,7 +4476,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7631-1"> @@ -4508,7 +4509,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4329-0"> @@ -4516,7 +4517,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4345-1"> @@ -4540,7 +4541,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4377-8"> @@ -4573,7 +4574,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4437-7"> @@ -4581,7 +4582,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4453-8"> @@ -4605,7 +4606,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4485-3"> @@ -4638,7 +4639,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4925-8"> @@ -4646,7 +4647,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4941-1"> @@ -4679,7 +4680,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath4973-3"> @@ -4731,7 +4732,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7903-1"> @@ -4739,7 +4740,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7919-4"> @@ -4772,7 +4773,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath7951-2"> @@ -4796,7 +4797,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17117"> @@ -4804,7 +4805,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17121"> @@ -4837,7 +4838,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17132"> @@ -4870,7 +4871,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17143"> @@ -4878,7 +4879,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17147"> @@ -4902,7 +4903,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath17158"> @@ -4990,7 +4991,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5841-3"> @@ -4998,7 +4999,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5857-5"> @@ -5006,7 +5007,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5873-66"> @@ -5014,7 +5015,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5889-3"> @@ -5022,7 +5023,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5905-9"> @@ -5057,7 +5058,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5937-4"> @@ -5092,7 +5093,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath5969-7"> @@ -5127,7 +5128,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6001-5"> @@ -5162,7 +5163,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6033-9"> @@ -5197,7 +5198,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6065-5"> @@ -5232,7 +5233,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6097-7"> @@ -5267,7 +5268,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6129-8"> @@ -5302,7 +5303,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6169-9"> @@ -5310,7 +5311,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6185-0"> @@ -5345,7 +5346,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6217-2"> @@ -5380,7 +5381,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6273-8"> @@ -5388,7 +5389,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6289-3"> @@ -5423,7 +5424,7 @@ clipPathUnits="userSpaceOnUse" id="clipPath6321-6"> @@ -5513,7 +5514,7 @@ id="bullet-char-template(57356)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5521,7 +5522,7 @@ id="bullet-char-template(57354)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5529,7 +5530,7 @@ id="bullet-char-template(10146)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5537,7 +5538,7 @@ id="bullet-char-template(10132)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5545,7 +5546,7 @@ id="bullet-char-template(10007)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5553,7 +5554,7 @@ id="bullet-char-template(10004)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5561,7 +5562,7 @@ id="bullet-char-template(9679)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5569,7 +5570,7 @@ id="bullet-char-template(8226)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -5577,7 +5578,7 @@ id="bullet-char-template(8211)" transform="scale(4.8828125e-4,-4.8828125e-4)"> @@ -10280,6 +10281,254 @@ transform="matrix(-0.3,0,0,-0.3,0.69,0)" inkscape:connector-curvature="0" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -10299,7 +10548,7 @@ inkscape:label="background" style="display:none" sodipodi:insensitive="true" - transform="translate(9.5291677,71.377308)"> + transform="translate(-32.46875,315.85439)"> + transform="translate(-32.46875,315.85439)"> - - + transform="translate(-32.46875,315.85439)" + style="display:inline" + sodipodi:insensitive="true"> @@ -36348,10 +38195,10 @@ id="layer2-9" inkscape:label="Eagle_speed_sensor" style="display:inline" - transform="matrix(0.77129601,0,0,0.77129601,-838.29825,-434.77767)" /> + transform="matrix(0.77129601,0,0,0.77129601,-880.29617,-190.30059)" /> + transform="matrix(0.77129601,0,0,0.77129601,-757.27445,90.740389)" /> diff --git a/ground/openpilotgcs/src/plugins/setupwizard/resources/fixedwing-shapes-wizard-no-numbers.svg b/ground/openpilotgcs/src/plugins/setupwizard/resources/fixedwing-shapes-wizard-no-numbers.svg index 8f250956c..18656681f 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/resources/fixedwing-shapes-wizard-no-numbers.svg +++ b/ground/openpilotgcs/src/plugins/setupwizard/resources/fixedwing-shapes-wizard-no-numbers.svg @@ -14,9 +14,9 @@ id="Layer_1" x="0px" y="0px" - width="792" - height="2016" - viewBox="0 0 792 2016" + width="653.61542" + height="2094.717" + viewBox="0 0 653.61542 2094.717" enable-background="new 0 0 792 1008" xml:space="preserve" inkscape:version="0.48.5 r10040" @@ -258,22 +258,6 @@ x2="281.74301" y2="630.1615" />6 \ No newline at end of file + d="M 449.683,830.161 V 821.571 H 453.494 C 454.26,821.571 454.842,821.648 455.24,821.8 C 455.636,821.954 455.957,822.227 456.195,822.617 C 456.431,823.007 456.55,823.439 456.55,823.912 C 456.55,824.52 456.353,825.035 455.958,825.453 C 455.562,825.871 454.954,826.137 454.13,826.25 C 454.431,826.396 454.659,826.537 454.818,826.678 C 455.15,826.985 455.464,827.366 455.759,827.823 L 457.253,830.161 H 455.823 L 454.684,828.374 C 454.352,827.858 454.08,827.464 453.866,827.189 C 453.651,826.916 453.46,826.723 453.29,826.616 C 453.12,826.507 452.946,826.428 452.769,826.387 C 452.64,826.362 452.429,826.346 452.136,826.346 H 450.82 V 830.16 L 449.683,830.161 L 449.683,830.161 z M 450.819,825.362 H 453.26 C 453.781,825.362 454.186,825.306 454.481,825.201 C 454.774,825.094 454.997,824.922 455.149,824.683 C 455.299,824.448 455.378,824.192 455.378,823.912 C 455.378,823.506 455.232,823.172 454.937,822.91 C 454.642,822.647 454.175,822.515 453.541,822.515 H 450.822 L 450.819,825.362 L 450.819,825.362 z" + id="path4097-7" /> + + + +4 +6 + \ No newline at end of file diff --git a/ground/openpilotgcs/src/plugins/setupwizard/setupwizard.cpp b/ground/openpilotgcs/src/plugins/setupwizard/setupwizard.cpp index ab6861823..29ec8bae3 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/setupwizard.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/setupwizard.cpp @@ -371,7 +371,7 @@ QString SetupWizard::getSummaryText() summary.append(tr("Standard ESC (50 Hz)")); break; case ESC_RAPID: - summary.append(tr("Rapid ESC (400 Hz)")); + summary.append(tr("Rapid ESC (500 Hz)")); break; default: summary.append(tr("Unknown")); diff --git a/ground/openpilotgcs/src/plugins/setupwizard/wizardResources.qrc b/ground/openpilotgcs/src/plugins/setupwizard/wizardResources.qrc index c320a20e8..898f43f5f 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/wizardResources.qrc +++ b/ground/openpilotgcs/src/plugins/setupwizard/wizardResources.qrc @@ -29,6 +29,8 @@ resources/bttn-calculate-up.png resources/bttn-turbo-down.png resources/bttn-turbo-up.png + resources/bttn-rapid-up.png + resources/bttn-rapid-dwn.png resources/bttn-servo-digital-dwn.png resources/bttn-servo-digital-up.png resources/bttn-servo-standard-dwn.png diff --git a/make/apps-defs.mk b/make/apps-defs.mk index 1544e4c10..23fcf3156 100644 --- a/make/apps-defs.mk +++ b/make/apps-defs.mk @@ -111,6 +111,7 @@ SRC += $(MATHLIB)/pid.c SRC += $(MATHLIB)/mathmisc.c SRC += $(MATHLIB)/butterworth.c SRC += $(FLIGHTLIB)/printf-stdarg.c +SRC += $(FLIGHTLIB)/optypes.c ## Modules SRC += $(foreach mod, $(MODULES), $(sort $(wildcard $(OPMODULEDIR)/$(mod)/*.c))) diff --git a/make/unittest.mk b/make/unittest.mk index 5963f5567..2190a6ab4 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -52,6 +52,10 @@ CXXFLAGS += -g -Wall -Wextra # Flags passed to the C compiler CONLYFLAGS += -std=gnu99 +# UNIT_TEST allows to for example to have optional test fixture code enabled or private code exposed in application modules. +CFLAGS += -DUNIT_TEST +CPPFLAGS += -DUNIT_TEST + # Common compiler flags CFLAGS += -O0 -g CFLAGS += -Wall -Werror diff --git a/shared/uavobjectdefinition/attitudestate.xml b/shared/uavobjectdefinition/attitudestate.xml index 98ceaa3c7..0d5dc0c08 100644 --- a/shared/uavobjectdefinition/attitudestate.xml +++ b/shared/uavobjectdefinition/attitudestate.xml @@ -10,7 +10,7 @@ - +