void gpsInit(serialConfig_t *initialSerialConfig, gpsConfig_t *initialGpsConfig) { gpsState.serialConfig = initialSerialConfig; gpsState.gpsConfig = initialGpsConfig; gpsState.baudrateIndex = 0; gpsStats.errors = 0; gpsStats.timeouts = 0; gpsResetSolution(); // init gpsData structure. if we're not actually enabled, don't bother doing anything else gpsState.autoConfigStep = 0; gpsState.lastMessageMs = millis(); gpsSetState(GPS_UNKNOWN); if (gpsProviders[gpsState.gpsConfig->provider].type == GPS_TYPE_BUS) { gpsSetState(GPS_INITIALIZING); return; } if (gpsProviders[gpsState.gpsConfig->provider].type == GPS_TYPE_SERIAL) { serialPortConfig_t * gpsPortConfig = findSerialPortConfig(FUNCTION_GPS); if (!gpsPortConfig) { featureClear(FEATURE_GPS); } else { while (gpsToSerialBaudRate[gpsState.baudrateIndex] != gpsPortConfig->gps_baudrateIndex) { gpsState.baudrateIndex++; if (gpsState.baudrateIndex >= GPS_BAUDRATE_COUNT) { gpsState.baudrateIndex = 0; break; } } portMode_t mode = gpsProviders[gpsState.gpsConfig->provider].portMode; // no callback - buffer will be consumed in gpsThread() gpsState.gpsPort = openSerialPort(gpsPortConfig->identifier, FUNCTION_GPS, NULL, baudRates[gpsToSerialBaudRate[gpsState.baudrateIndex]], mode, SERIAL_NOT_INVERTED); if (!gpsState.gpsPort) { featureClear(FEATURE_GPS); } else { gpsSetState(GPS_INITIALIZING); return; } } } }
void gpsInit(serialConfig_t *initialSerialConfig, gpsConfig_t *initialGpsConfig) { serialConfig = initialSerialConfig; gpsData.baudrateIndex = 0; gpsData.errors = 0; gpsData.timeouts = 0; memset(gpsPacketLog, 0x00, sizeof(gpsPacketLog)); gpsConfig = initialGpsConfig; // init gpsData structure. if we're not actually enabled, don't bother doing anything else gpsSetState(GPS_UNKNOWN); gpsData.lastMessage = millis(); serialPortConfig_t *gpsPortConfig = findSerialPortConfig(FUNCTION_GPS); if (!gpsPortConfig) { featureClear(FEATURE_GPS); return; } while (gpsInitData[gpsData.baudrateIndex].baudrateIndex != gpsPortConfig->gps_baudrateIndex) { gpsData.baudrateIndex++; if (gpsData.baudrateIndex >= GPS_INIT_DATA_ENTRY_COUNT) { gpsData.baudrateIndex = DEFAULT_BAUD_RATE_INDEX; break; } } portMode_t mode = MODE_RXTX; // only RX is needed for NMEA-style GPS #if !defined(COLIBRI_RACE) || !defined(LUX_RACE) if (gpsConfig->provider == GPS_NMEA) mode &= ~MODE_TX; #endif // no callback - buffer will be consumed in gpsThread() gpsPort = openSerialPort(gpsPortConfig->identifier, FUNCTION_GPS, NULL, gpsInitData[gpsData.baudrateIndex].baudrateIndex, mode, SERIAL_NOT_INVERTED); if (!gpsPort) { featureClear(FEATURE_GPS); return; } // signal GPS "thread" to initialize when it gets to it gpsSetState(GPS_INITIALIZING); }
// alternative defaults settings for AlienFlight targets void targetConfiguration(void) { featureClear(FEATURE_ONESHOT125); masterConfig.mag_hardware = MAG_NONE; // disabled by default masterConfig.rxConfig.spektrum_sat_bind = 5; masterConfig.rxConfig.spektrum_sat_bind_autoreset = 1; masterConfig.motor_pwm_rate = 32000; masterConfig.failsafeConfig.failsafe_delay = 2; masterConfig.failsafeConfig.failsafe_off_delay = 0; masterConfig.gyro_sync_denom = 2; masterConfig.pid_process_denom = 1; currentProfile->pidProfile.P8[ROLL] = 90; currentProfile->pidProfile.I8[ROLL] = 44; currentProfile->pidProfile.D8[ROLL] = 60; currentProfile->pidProfile.P8[PITCH] = 90; currentProfile->pidProfile.I8[PITCH] = 44; currentProfile->pidProfile.D8[PITCH] = 60; parseRcChannels("TAER1234", &masterConfig.rxConfig); masterConfig.customMotorMixer[0] = (motorMixer_t){ 1.0f, -0.414178f, 1.0f, -1.0f }; // REAR_R masterConfig.customMotorMixer[1] = (motorMixer_t){ 1.0f, -0.414178f, -1.0f, 1.0f }; // FRONT_R masterConfig.customMotorMixer[2] = (motorMixer_t){ 1.0f, 0.414178f, 1.0f, 1.0f }; // REAR_L masterConfig.customMotorMixer[3] = (motorMixer_t){ 1.0f, 0.414178f, -1.0f, -1.0f }; // FRONT_L masterConfig.customMotorMixer[4] = (motorMixer_t){ 1.0f, -1.0f, -0.414178f, -1.0f }; // MIDFRONT_R masterConfig.customMotorMixer[5] = (motorMixer_t){ 1.0f, 1.0f, -0.414178f, 1.0f }; // MIDFRONT_L masterConfig.customMotorMixer[6] = (motorMixer_t){ 1.0f, -1.0f, 0.414178f, 1.0f }; // MIDREAR_R masterConfig.customMotorMixer[7] = (motorMixer_t){ 1.0f, 1.0f, 0.414178f, -1.0f }; // MIDREAR_L#endif }
void serialRxInit(rxConfig_t *rxConfig) { bool enabled = false; switch (rxConfig->serialrx_provider) { case SERIALRX_SPEKTRUM1024: case SERIALRX_SPEKTRUM2048: enabled = spektrumInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SBUS: enabled = sbusInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SUMD: enabled = sumdInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SUMH: enabled = sumhInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_XBUS_MODE_B: case SERIALRX_XBUS_MODE_B_RJ01: enabled = xBusInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; } if (!enabled) { featureClear(FEATURE_RX_SERIAL); rcReadRawFunc = nullReadRawRC; } }
void pwmDriverInitialize(void) { driverEnabled = (pwmDrivers[driverImplementationIndex].initFunction)(); if (!driverEnabled) { featureClear(FEATURE_PWM_SERVO_DRIVER); } }
static long cmsx_Ledstrip_FeatureWriteback(void) { if (cmsx_FeatureLedstrip) featureSet(FEATURE_LED_STRIP); else featureClear(FEATURE_LED_STRIP); return 0; }
static long cmsx_Blackbox_FeatureWriteback(void) { if (cmsx_FeatureBlackbox) featureSet(FEATURE_BLACKBOX); else featureClear(FEATURE_BLACKBOX); return 0; }
static long cmsx_Blackbox_FeatureWriteback(void) { if (cmsx_FeatureBlackbox) featureSet(FEATURE_BLACKBOX); else featureClear(FEATURE_BLACKBOX); blackboxConfigMutable()->rate_denom = blackboxConfig_rate_denom; return 0; }
static void cliFeature(char *cmdline) { uint32_t i; uint32_t len; uint32_t mask; len = strlen(cmdline); mask = featureMask(); if (len == 0) { cliPrint("Enabled features: "); for (i = 0; ; i++) { if (featureNames[i] == NULL) break; if (mask & (1 << i)) printf("%s ", featureNames[i]); } cliPrint("\r\n"); } else if (strncasecmp(cmdline, "list", len) == 0) { cliPrint("Available features: "); for (i = 0; ; i++) { if (featureNames[i] == NULL) break; printf("%s ", featureNames[i]); } cliPrint("\r\n"); return; } else { bool remove = false; if (cmdline[0] == '-') { // remove feature remove = true; cmdline++; // skip over - len--; } for (i = 0; ; i++) { if (featureNames[i] == NULL) { cliPrint("Invalid feature name...\r\n"); break; } if (strncasecmp(cmdline, featureNames[i], len) == 0) { if (remove) { featureClear(1 << i); cliPrint("Disabled "); } else { featureSet(1 << i); cliPrint("Enabled "); } printf("%s\r\n", featureNames[i]); break; } } } }
void osdExitMenu(void *ptr) { max7456ClearScreen(); max7456Write(5, 3, "RESTARTING IMU..."); max7456RefreshAll(); stopMotors(); stopPwmAllMotors(); delay(200); if (ptr) { // save local variables to configuration if (featureBlackbox) featureSet(FEATURE_BLACKBOX); else featureClear(FEATURE_BLACKBOX); if (featureLedstrip) featureSet(FEATURE_LED_STRIP); else featureClear(FEATURE_LED_STRIP); #if defined(VTX) || defined(USE_RTC6705) if (featureVtx) featureSet(FEATURE_VTX); else featureClear(FEATURE_VTX); #endif // VTX || USE_RTC6705 #ifdef VTX masterConfig.vtxBand = vtxBand; masterConfig.vtx_channel = vtxChannel - 1; #endif // VTX #ifdef USE_RTC6705 masterConfig.vtx_channel = vtxBand * 8 + vtxChannel - 1; #endif // USE_RTC6705 saveConfigAndNotify(); } systemReset(); }
void serialRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig) { bool enabled = false; switch (rxConfig->serialrx_provider) { #ifdef USE_SERIALRX_SPEKTRUM case SERIALRX_SPEKTRUM1024: enabled = spektrumInit(rxConfig, rxRuntimeConfig); break; case SERIALRX_SPEKTRUM2048: enabled = spektrumInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_SBUS case SERIALRX_SBUS: enabled = sbusInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_SUMD case SERIALRX_SUMD: enabled = sumdInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_SUMH case SERIALRX_SUMH: enabled = sumhInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_XBUS case SERIALRX_XBUS_MODE_B: case SERIALRX_XBUS_MODE_B_RJ01: enabled = xBusInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_IBUS case SERIALRX_IBUS: enabled = ibusInit(rxConfig, rxRuntimeConfig); break; #endif #ifdef USE_SERIALRX_JETIEXBUS case SERIALRX_JETIEXBUS: enabled = jetiExBusInit(rxConfig, rxRuntimeConfig); break; #endif default: enabled = false; break; } if (!enabled) { featureClear(FEATURE_RX_SERIAL); rxRuntimeConfig->rcReadRawFn = nullReadRawRC; } }
// alternative defaults settings for AlienFlight targets void targetConfiguration(void) { featureClear(FEATURE_ONESHOT125); masterConfig.rxConfig.spektrum_sat_bind = 5; masterConfig.rxConfig.spektrum_sat_bind_autoreset = 1; masterConfig.motor_pwm_rate = 32000; masterConfig.failsafeConfig.failsafe_delay = 2; masterConfig.failsafeConfig.failsafe_off_delay = 0; parseRcChannels("TAER1234", &masterConfig.rxConfig); masterConfig.customMotorMixer[0] = (motorMixer_t){ 1.0f, -0.414178f, 1.0f, -1.0f }; // REAR_R masterConfig.customMotorMixer[1] = (motorMixer_t){ 1.0f, -0.414178f, -1.0f, 1.0f }; // FRONT_R masterConfig.customMotorMixer[2] = (motorMixer_t){ 1.0f, 0.414178f, 1.0f, 1.0f }; // REAR_L masterConfig.customMotorMixer[3] = (motorMixer_t){ 1.0f, 0.414178f, -1.0f, -1.0f }; // FRONT_L masterConfig.customMotorMixer[4] = (motorMixer_t){ 1.0f, -1.0f, -0.414178f, -1.0f }; // MIDFRONT_R masterConfig.customMotorMixer[5] = (motorMixer_t){ 1.0f, 1.0f, -0.414178f, 1.0f }; // MIDFRONT_L masterConfig.customMotorMixer[6] = (motorMixer_t){ 1.0f, -1.0f, 0.414178f, 1.0f }; // MIDREAR_R masterConfig.customMotorMixer[7] = (motorMixer_t){ 1.0f, 1.0f, 0.414178f, -1.0f }; // MIDREAR_L#endif }
void serialRxInit(rxConfig_t *rxConfig) { bool enabled = false; switch (rxConfig->serialrx_provider) { case SERIALRX_SPEKTRUM1024: rxRefreshRate = 22000; enabled = spektrumInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SPEKTRUM2048: rxRefreshRate = 11000; enabled = spektrumInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SBUS: rxRefreshRate = 11000; enabled = sbusInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SUMD: rxRefreshRate = 11000; enabled = sumdInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_SUMH: rxRefreshRate = 11000; enabled = sumhInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_XBUS_MODE_B: case SERIALRX_XBUS_MODE_B_RJ01: rxRefreshRate = 11000; enabled = xBusInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; case SERIALRX_IBUS: rxRefreshRate = 20000; // TODO - Verify speed enabled = ibusInit(rxConfig, &rxRuntimeConfig, &rcReadRawFunc); break; } if (!enabled) { featureClear(FEATURE_RX_SERIAL); rcReadRawFunc = nullReadRawRC; } }
// When using PWM input GPS usage reduces number of available channels by 2 - see pwm_common.c/pwmInit() void gpsInit(serialConfig_t *initialSerialConfig, gpsConfig_t *initialGpsConfig) { serialConfig = initialSerialConfig; gpsData.baudrateIndex = 0; while (gpsInitData[gpsData.baudrateIndex].baudrate != serialConfig->gps_baudrate) { gpsData.baudrateIndex++; if (gpsData.baudrateIndex >= GPS_INIT_DATA_ENTRY_COUNT) { gpsData.baudrateIndex = DEFAULT_BAUD_RATE_INDEX; break; } } gpsConfig = initialGpsConfig; // init gpsData structure. if we're not actually enabled, don't bother doing anything else gpsSetState(GPS_UNKNOWN); gpsData.lastMessage = millis(); gpsData.errors = 0; portMode_t mode = MODE_RXTX; // only RX is needed for NMEA-style GPS if (gpsConfig->provider == GPS_NMEA) mode = MODE_RX; // no callback - buffer will be consumed in gpsThread() gpsPort = openSerialPort(FUNCTION_GPS, NULL, gpsInitData[gpsData.baudrateIndex].baudrate, mode, SERIAL_NOT_INVERTED); if (!gpsPort) { featureClear(FEATURE_GPS); return; } // signal GPS "thread" to initialize when it gets to it gpsSetState(GPS_INITIALIZING); }
void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL); featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } #if defined(NAV) // Ensure sane values of navConfig settings validateNavConfig(&masterConfig.navConfig); #endif if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #ifdef STM32F10X // avoid overloading the CPU on F1 targets when using gyro sync and GPS. if (masterConfig.gyroSync && masterConfig.gyroSyncDenominator < 2 && featureConfigured(FEATURE_GPS)) { masterConfig.gyroSyncDenominator = 2; } // avoid overloading the CPU when looptime < 2000 and GPS if (masterConfig.looptime && featureConfigured(FEATURE_GPS)) { masterConfig.looptime = 2000; } #endif #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(NAZE) && defined(SONAR) if (featureConfigured(FEATURE_RX_PARALLEL_PWM) && featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_USART3) if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif #ifdef STM32F303xC // hardware supports serial port inversion, make users life easier for those that want to connect SBus RX's masterConfig.telemetryConfig.telemetry_inversion = 1; #endif #if defined(CC3D) #if defined(CC3D_PPM1) #if defined(SONAR) && defined(USE_SOFTSERIAL1) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { featureClear(FEATURE_SONAR); } #endif #else #if defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #endif // CC3D_PPM1 #endif // CC3D #if defined(COLIBRI_RACE) masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; if(featureConfigured(FEATURE_RX_SERIAL)) { masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL; } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } /* * If provided predefined mixer setup is disabled, fallback to default one */ if (!isMixerEnabled(masterConfig.mixerMode)) { masterConfig.mixerMode = DEFAULT_MIXER; } }
void validateAndFixConfig(void) { if((masterConfig.motorConfig.motorPwmProtocol == PWM_TYPE_BRUSHED) && (masterConfig.motorConfig.mincommand < 1000)){ masterConfig.motorConfig.mincommand = 1000; } if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP) || featureConfigured(FEATURE_RX_SPI))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_SPI); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_SPI); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_SPI); } if (featureConfigured(FEATURE_RX_SPI)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_MSP); } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_SPI); #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #ifdef USE_SOFTSPI if (featureConfigured(FEATURE_SOFTSPI)) { featureClear(FEATURE_RX_PPM | FEATURE_RX_PARALLEL_PWM | FEATURE_SOFTSERIAL | FEATURE_VBAT); #if defined(STM32F10X) featureClear(FEATURE_LED_STRIP); // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif } #endif #if defined(NAZE) && defined(SONAR) if (featureConfigured(FEATURE_RX_PARALLEL_PWM) && featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_UART3) if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DASHBOARD)) { featureClear(FEATURE_DASHBOARD); } #endif #if defined(CC3D) && defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #if defined(COLIBRI_RACE) masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; if (featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_MSP); featureSet(FEATURE_RX_PPM); } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } #if defined(TARGET_VALIDATECONFIG) targetValidateConfiguration(&masterConfig); #endif }
void validateAndFixConfig(void) { if (!(feature(FEATURE_RX_PARALLEL_PWM) || feature(FEATURE_RX_PPM) || feature(FEATURE_RX_SERIAL) || feature(FEATURE_RX_MSP))) { featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM } if (feature(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM); } if (feature(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL); featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_PARALLEL_PWM)) { #if defined(STM32F103_MD) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports featureClear(FEATURE_CURRENT_METER); #ifdef SONAR // sonar needs a free PWM port featureClear(FEATURE_SONAR); #endif #endif #if defined(STM32F103_MD) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #if defined(STM32F103_MD) // led strip needs the same timer as softserial if (feature(FEATURE_SOFTSERIAL)) { featureClear(FEATURE_LED_STRIP); } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; applySerialConfigToPortFunctions(serialConfig); if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); }
void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_SERIAL | FEATURE_RX_MSP); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM); } #ifdef STM32F10X // avoid overloading the CPU on F1 targets when using gyro sync and GPS. if (imuConfig()->gyroSync && imuConfig()->gyroSyncDenominator < 2 && featureConfigured(FEATURE_GPS)) { imuConfig()->gyroSyncDenominator = 2; } #endif #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_UART3) if (doesConfigurationUsePort(SERIAL_PORT_UART3) && featureConfigured(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif #ifdef STM32F303xC // hardware supports serial port inversion, make users life easier for those that want to connect SBus RX's #ifdef TELEMETRY telemetryConfig()->telemetry_inversion = 1; #endif #endif /* * The retarded_arm setting is incompatible with pid_at_min_throttle because full roll causes the craft to roll over on the ground. * The pid_at_min_throttle implementation ignores yaw on the ground, but doesn't currently ignore roll when retarded_arm is enabled. */ if (armingConfig()->retarded_arm && mixerConfig()->pid_at_min_throttle) { mixerConfig()->pid_at_min_throttle = 0; } #if defined(LED_STRIP) && defined(TRANSPONDER) && !defined(UNIT_TEST) if ((WS2811_DMA_TC_FLAG == TRANSPONDER_DMA_TC_FLAG) && featureConfigured(FEATURE_TRANSPONDER) && featureConfigured(FEATURE_LED_STRIP)) { featureClear(FEATURE_LED_STRIP); } #endif #if defined(CC3D) && defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #if defined(COLIBRI_RACE) serialConfig()->portConfigs[0].functionMask = FUNCTION_MSP; if (featureConfigured(FEATURE_RX_SERIAL)) { serialConfig()->portConfigs[2].functionMask = FUNCTION_RX_SERIAL; } #endif if (!isSerialConfigValid(serialConfig())) { PG_RESET_CURRENT(serialConfig); } #if defined(USE_VCP) serialConfig()->portConfigs[0].functionMask = FUNCTION_MSP; #endif }
static void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_SERIAL | FEATURE_RX_MSP); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM); } // The retarded_arm setting is incompatible with pid_at_min_throttle because full roll causes the craft to roll over on the ground. // The pid_at_min_throttle implementation ignores yaw on the ground, but doesn't currently ignore roll when retarded_arm is enabled. if (armingConfig()->retarded_arm && mixerConfig()->pid_at_min_throttle) { mixerConfig()->pid_at_min_throttle = 0; } if (gyroConfig()->gyro_soft_notch_hz < gyroConfig()->gyro_soft_notch_cutoff_hz) { gyroConfig()->gyro_soft_notch_hz = gyroConfig()->gyro_soft_notch_cutoff_hz; } #if defined(LED_STRIP) #if (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(TRANSPONDER) && !defined(UNIT_TEST) if ((WS2811_DMA_TC_FLAG == TRANSPONDER_DMA_TC_FLAG) && featureConfigured(FEATURE_TRANSPONDER) && featureConfigured(FEATURE_LED_STRIP)) { featureClear(FEATURE_LED_STRIP); } #endif #endif // LED_STRIP #if defined(CC3D) #if defined(DISPLAY) && defined(USE_UART3) if (featureConfigured(FEATURE_DISPLAY) && doesConfigurationUsePort(SERIAL_PORT_UART3)) { featureClear(FEATURE_DISPLAY); } #endif #if defined(SONAR) && defined(USE_SOFTSERIAL1) if (featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_SOFTSERIAL)) { featureClear(FEATURE_SONAR); } #endif #if defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #endif // CC3D #if defined(COLIBRI_RACE) serialConfig()->portConfigs[0].functionMask = FUNCTION_MSP_SERVER; if (featureConfigured(FEATURE_RX_SERIAL)) { serialConfig()->portConfigs[2].functionMask = FUNCTION_RX_SERIAL; } #endif #if defined(SPRACINGF3NEO_REV) && (SPRACINGF3NEO_REV < 5) if (featureConfigured(FEATURE_OSD) && featureConfigured(FEATURE_TRANSPONDER)) { featureClear(FEATURE_TRANSPONDER); } if (featureConfigured(FEATURE_OSD) && featureConfigured(FEATURE_LED_STRIP)) { featureClear(FEATURE_LED_STRIP); } #endif if (!isSerialConfigValid(serialConfig())) { PG_RESET_CURRENT(serialConfig); } #if defined(USE_VCP) serialConfig()->portConfigs[0].functionMask = FUNCTION_MSP_SERVER; #endif }
void init(void) { printfSupportInit(); initEEPROM(); ensureEEPROMContainsValidData(); readEEPROM(); systemState |= SYSTEM_STATE_CONFIG_LOADED; systemInit(); //i2cSetOverclock(masterConfig.i2c_overclock); // initialize IO (needed for all IO operations) IOInitGlobal(); debugMode = masterConfig.debug_mode; #ifdef USE_HARDWARE_REVISION_DETECTION detectHardwareRevision(); #endif // Latch active features to be used for feature() in the remainder of init(). latchActiveFeatures(); #ifdef ALIENFLIGHTF3 ledInit(hardwareRevision == AFF3_REV_1 ? false : true); #else ledInit(false); #endif LED2_ON; #ifdef USE_EXTI EXTIInit(); #endif #if defined(BUTTONS) gpio_config_t buttonAGpioConfig = { BUTTON_A_PIN, Mode_IPU, Speed_2MHz }; gpioInit(BUTTON_A_PORT, &buttonAGpioConfig); gpio_config_t buttonBGpioConfig = { BUTTON_B_PIN, Mode_IPU, Speed_2MHz }; gpioInit(BUTTON_B_PORT, &buttonBGpioConfig); // Check status of bind plug and exit if not active delayMicroseconds(10); // allow GPIO configuration to settle if (!isMPUSoftReset()) { uint8_t secondsRemaining = 5; bool bothButtonsHeld; do { bothButtonsHeld = !digitalIn(BUTTON_A_PORT, BUTTON_A_PIN) && !digitalIn(BUTTON_B_PORT, BUTTON_B_PIN); if (bothButtonsHeld) { if (--secondsRemaining == 0) { resetEEPROM(); systemReset(); } delay(1000); LED0_TOGGLE; } } while (bothButtonsHeld); } #endif #ifdef SPEKTRUM_BIND if (feature(FEATURE_RX_SERIAL)) { switch (masterConfig.rxConfig.serialrx_provider) { case SERIALRX_SPEKTRUM1024: case SERIALRX_SPEKTRUM2048: // Spektrum satellite binding if enabled on startup. // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup. // The rest of Spektrum initialization will happen later - via spektrumInit() spektrumBind(&masterConfig.rxConfig); break; } } #endif delay(100); timerInit(); // timer must be initialized before any channel is allocated dmaInit(); #if defined(AVOID_UART1_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART1 : SERIAL_PORT_NONE); #elif defined(AVOID_UART2_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART2 : SERIAL_PORT_NONE); #elif defined(AVOID_UART3_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART3 : SERIAL_PORT_NONE); #else serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), SERIAL_PORT_NONE); #endif #ifdef USE_SERVOS mixerInit(masterConfig.mixerMode, masterConfig.customMotorMixer, masterConfig.customServoMixer); #else mixerInit(masterConfig.mixerMode, masterConfig.customMotorMixer); #endif drv_pwm_config_t pwm_params; memset(&pwm_params, 0, sizeof(pwm_params)); #ifdef SONAR if (feature(FEATURE_SONAR)) { const sonarHardware_t *sonarHardware = sonarGetHardwareConfiguration(masterConfig.batteryConfig.currentMeterType); if (sonarHardware) { pwm_params.useSonar = true; pwm_params.sonarIOConfig.triggerTag = sonarHardware->triggerTag; pwm_params.sonarIOConfig.echoTag = sonarHardware->echoTag; } } #endif // when using airplane/wing mixer, servo/motor outputs are remapped if (masterConfig.mixerMode == MIXER_AIRPLANE || masterConfig.mixerMode == MIXER_FLYING_WING || masterConfig.mixerMode == MIXER_CUSTOM_AIRPLANE) pwm_params.airplane = true; else pwm_params.airplane = false; #if defined(USE_UART2) && defined(STM32F10X) pwm_params.useUART2 = doesConfigurationUsePort(SERIAL_PORT_USART2); #endif #ifdef STM32F303xC pwm_params.useUART2 = doesConfigurationUsePort(SERIAL_PORT_USART2); pwm_params.useUART3 = doesConfigurationUsePort(SERIAL_PORT_USART3); #endif #if defined(USE_UART2) && defined(STM32F40_41xxx) pwm_params.useUART2 = doesConfigurationUsePort(SERIAL_PORT_USART2); #endif #if defined(USE_UART6) && defined(STM32F40_41xxx) pwm_params.useUART6 = doesConfigurationUsePort(SERIAL_PORT_USART6); #endif pwm_params.useVbat = feature(FEATURE_VBAT); pwm_params.useSoftSerial = feature(FEATURE_SOFTSERIAL); pwm_params.useParallelPWM = feature(FEATURE_RX_PARALLEL_PWM); pwm_params.useRSSIADC = feature(FEATURE_RSSI_ADC); pwm_params.useCurrentMeterADC = feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC; pwm_params.useLEDStrip = feature(FEATURE_LED_STRIP); pwm_params.usePPM = feature(FEATURE_RX_PPM); pwm_params.useSerialRx = feature(FEATURE_RX_SERIAL); #ifdef USE_SERVOS pwm_params.useServos = isMixerUsingServos(); pwm_params.useChannelForwarding = feature(FEATURE_CHANNEL_FORWARDING); pwm_params.servoCenterPulse = masterConfig.escAndServoConfig.servoCenterPulse; pwm_params.servoPwmRate = masterConfig.servo_pwm_rate; #endif bool use_unsyncedPwm = masterConfig.use_unsyncedPwm || masterConfig.motor_pwm_protocol == PWM_TYPE_CONVENTIONAL || masterConfig.motor_pwm_protocol == PWM_TYPE_BRUSHED; // Configurator feature abused for enabling Fast PWM pwm_params.useFastPwm = (masterConfig.motor_pwm_protocol != PWM_TYPE_CONVENTIONAL && masterConfig.motor_pwm_protocol != PWM_TYPE_BRUSHED); pwm_params.pwmProtocolType = masterConfig.motor_pwm_protocol; pwm_params.motorPwmRate = use_unsyncedPwm ? masterConfig.motor_pwm_rate : 0; pwm_params.idlePulse = masterConfig.escAndServoConfig.mincommand; if (feature(FEATURE_3D)) pwm_params.idlePulse = masterConfig.flight3DConfig.neutral3d; if (masterConfig.motor_pwm_protocol == PWM_TYPE_BRUSHED) { featureClear(FEATURE_3D); pwm_params.idlePulse = 0; // brushed motors } #ifdef CC3D pwm_params.useBuzzerP6 = masterConfig.use_buzzer_p6 ? true : false; #endif #ifndef SKIP_RX_PWM_PPM pwmRxInit(masterConfig.inputFilteringMode); #endif // pwmInit() needs to be called as soon as possible for ESC compatibility reasons pwmOutputConfiguration_t *pwmOutputConfiguration = pwmInit(&pwm_params); mixerUsePWMOutputConfiguration(pwmOutputConfiguration, use_unsyncedPwm); systemState |= SYSTEM_STATE_MOTORS_READY; #ifdef BEEPER beeperConfig_t beeperConfig = { .ioTag = IO_TAG(BEEPER), #ifdef BEEPER_INVERTED .isOD = false, .isInverted = true #else .isOD = true, .isInverted = false #endif }; #ifdef NAZE if (hardwareRevision >= NAZE32_REV5) { // naze rev4 and below used opendrain to PNP for buzzer. Rev5 and above use PP to NPN. beeperConfig.isOD = false; beeperConfig.isInverted = true; } #endif /* temp until PGs are implemented. */ #ifdef BLUEJAYF4 if (hardwareRevision <= BJF4_REV2) { beeperConfig.ioTag = IO_TAG(BEEPER_OPT); } #endif #ifdef CC3D if (masterConfig.use_buzzer_p6 == 1) beeperConfig.ioTag = IO_TAG(BEEPER_OPT); #endif beeperInit(&beeperConfig); #endif #ifdef INVERTER initInverter(); #endif #ifdef USE_BST bstInit(BST_DEVICE); #endif #ifdef USE_SPI #ifdef USE_SPI_DEVICE_1 spiInit(SPIDEV_1); #endif #ifdef USE_SPI_DEVICE_2 spiInit(SPIDEV_2); #endif #ifdef USE_SPI_DEVICE_3 #ifdef ALIENFLIGHTF3 if (hardwareRevision == AFF3_REV_2) { spiInit(SPIDEV_3); } #else spiInit(SPIDEV_3); #endif #endif #endif #ifdef VTX vtxInit(); #endif #ifdef USE_HARDWARE_REVISION_DETECTION updateHardwareRevision(); #endif #if defined(NAZE) if (hardwareRevision == NAZE32_SP) { serialRemovePort(SERIAL_PORT_SOFTSERIAL2); } else { serialRemovePort(SERIAL_PORT_USART3); } #endif #if defined(SPRACINGF3) && defined(SONAR) && defined(USE_SOFTSERIAL2) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { serialRemovePort(SERIAL_PORT_SOFTSERIAL2); } #endif #if defined(SPRACINGF3MINI) || defined(OMNIBUS) || defined(X_RACERSPI) #if defined(SONAR) && defined(USE_SOFTSERIAL1) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { serialRemovePort(SERIAL_PORT_SOFTSERIAL1); } #endif #endif #ifdef USE_I2C #if defined(NAZE) if (hardwareRevision != NAZE32_SP) { i2cInit(I2C_DEVICE); } else { if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { i2cInit(I2C_DEVICE); } } #elif defined(CC3D) if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { i2cInit(I2C_DEVICE); } #else i2cInit(I2C_DEVICE); #endif #endif #ifdef USE_ADC drv_adc_config_t adc_params; adc_params.enableVBat = feature(FEATURE_VBAT); adc_params.enableRSSI = feature(FEATURE_RSSI_ADC); adc_params.enableCurrentMeter = feature(FEATURE_CURRENT_METER); adc_params.enableExternal1 = false; #ifdef OLIMEXINO adc_params.enableExternal1 = true; #endif #ifdef NAZE // optional ADC5 input on rev.5 hardware adc_params.enableExternal1 = (hardwareRevision >= NAZE32_REV5); #endif adcInit(&adc_params); #endif initBoardAlignment(&masterConfig.boardAlignment); #ifdef DISPLAY if (feature(FEATURE_DISPLAY)) { displayInit(&masterConfig.rxConfig); } #endif #ifdef USE_RTC6705 if (feature(FEATURE_VTX)) { rtc6705_soft_spi_init(); current_vtx_channel = masterConfig.vtx_channel; rtc6705_soft_spi_set_channel(vtx_freq[current_vtx_channel]); rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power); } #endif #ifdef OSD if (feature(FEATURE_OSD)) { osdInit(); } #endif if (!sensorsAutodetect(&masterConfig.sensorAlignmentConfig, masterConfig.acc_hardware, masterConfig.mag_hardware, masterConfig.baro_hardware, masterConfig.mag_declination, masterConfig.gyro_lpf, masterConfig.gyro_sync_denom)) { // if gyro was not detected due to whatever reason, we give up now. failureMode(FAILURE_MISSING_ACC); } systemState |= SYSTEM_STATE_SENSORS_READY; LED1_ON; LED0_OFF; LED2_OFF; for (int i = 0; i < 10; i++) { LED1_TOGGLE; LED0_TOGGLE; delay(25); if (!(getBeeperOffMask() & (1 << (BEEPER_SYSTEM_INIT - 1)))) BEEP_ON; delay(25); BEEP_OFF; } LED0_OFF; LED1_OFF; #ifdef MAG if (sensors(SENSOR_MAG)) compassInit(); #endif imuInit(); mspInit(&masterConfig.serialConfig); #ifdef USE_CLI cliInit(&masterConfig.serialConfig); #endif failsafeInit(&masterConfig.rxConfig, masterConfig.flight3DConfig.deadband3d_throttle); rxInit(&masterConfig.rxConfig, masterConfig.modeActivationConditions); #ifdef GPS if (feature(FEATURE_GPS)) { gpsInit( &masterConfig.serialConfig, &masterConfig.gpsConfig ); navigationInit( &masterConfig.gpsProfile, ¤tProfile->pidProfile ); } #endif #ifdef SONAR if (feature(FEATURE_SONAR)) { sonarInit(); } #endif #ifdef LED_STRIP ledStripInit(masterConfig.ledConfigs, masterConfig.colors, masterConfig.modeColors, &masterConfig.specialColors); if (feature(FEATURE_LED_STRIP)) { ledStripEnable(); } #endif #ifdef TELEMETRY if (feature(FEATURE_TELEMETRY)) { telemetryInit(); } #endif #ifdef USB_CABLE_DETECTION usbCableDetectInit(); #endif #ifdef TRANSPONDER if (feature(FEATURE_TRANSPONDER)) { transponderInit(masterConfig.transponderData); transponderEnable(); transponderStartRepeating(); systemState |= SYSTEM_STATE_TRANSPONDER_ENABLED; } #endif #ifdef USE_FLASHFS #ifdef NAZE if (hardwareRevision == NAZE32_REV5) { m25p16_init(IOTAG_NONE); } #elif defined(USE_FLASH_M25P16) m25p16_init(IOTAG_NONE); #endif flashfsInit(); #endif #ifdef USE_SDCARD bool sdcardUseDMA = false; sdcardInsertionDetectInit(); #ifdef SDCARD_DMA_CHANNEL_TX #if defined(LED_STRIP) && defined(WS2811_DMA_CHANNEL) // Ensure the SPI Tx DMA doesn't overlap with the led strip #ifdef STM32F4 sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_STREAM; #else sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_CHANNEL; #endif #else sdcardUseDMA = true; #endif #endif sdcard_init(sdcardUseDMA); afatfs_init(); #endif if (masterConfig.gyro_lpf > 0 && masterConfig.gyro_lpf < 7) { masterConfig.pid_process_denom = 1; // When gyro set to 1khz always set pid speed 1:1 to sampling speed masterConfig.gyro_sync_denom = 1; } setTargetPidLooptime(gyro.targetLooptime * masterConfig.pid_process_denom); // Initialize pid looptime #ifdef BLACKBOX initBlackbox(); #endif if (masterConfig.mixerMode == MIXER_GIMBAL) { accSetCalibrationCycles(CALIBRATING_ACC_CYCLES); } gyroSetCalibrationCycles(); #ifdef BARO baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES); #endif // start all timers // TODO - not implemented yet timerStart(); ENABLE_STATE(SMALL_ANGLE); DISABLE_ARMING_FLAG(PREVENT_ARMING); #ifdef SOFTSERIAL_LOOPBACK // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly loopbackPort = (serialPort_t*)&(softSerialPorts[0]); if (!loopbackPort->vTable) { loopbackPort = openSoftSerial(0, NULL, 19200, SERIAL_NOT_INVERTED); } serialPrint(loopbackPort, "LOOPBACK\r\n"); #endif // Now that everything has powered up the voltage and cell count be determined. if (feature(FEATURE_VBAT | FEATURE_CURRENT_METER)) batteryInit(&masterConfig.batteryConfig); #ifdef DISPLAY if (feature(FEATURE_DISPLAY)) { #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY displayShowFixedPage(PAGE_GPS); #else displayResetPageCycling(); displayEnablePageCycling(); #endif } #endif #ifdef CJMCU LED2_ON; #endif // Latch active features AGAIN since some may be modified by init(). latchActiveFeatures(); motorControlEnable = true; systemState |= SYSTEM_STATE_READY; } #ifdef SOFTSERIAL_LOOPBACK void processLoopback(void) { if (loopbackPort) { uint8_t bytesWaiting; while ((bytesWaiting = serialRxBytesWaiting(loopbackPort))) { uint8_t b = serialRead(loopbackPort); serialWrite(loopbackPort, b); }; } } #else #define processLoopback() #endif void main_init(void) { init(); /* Setup scheduler */ schedulerInit(); rescheduleTask(TASK_GYROPID, gyro.targetLooptime); setTaskEnabled(TASK_GYROPID, true); if (sensors(SENSOR_ACC)) { setTaskEnabled(TASK_ACCEL, true); switch (gyro.targetLooptime) { // Switch statement kept in place to change acc rates in the future case 500: case 375: case 250: case 125: accTargetLooptime = 1000; break; default: case 1000: #ifdef STM32F10X accTargetLooptime = 1000; #else accTargetLooptime = 1000; #endif } rescheduleTask(TASK_ACCEL, accTargetLooptime); } setTaskEnabled(TASK_ATTITUDE, sensors(SENSOR_ACC)); setTaskEnabled(TASK_SERIAL, true); #ifdef BEEPER setTaskEnabled(TASK_BEEPER, true); #endif setTaskEnabled(TASK_BATTERY, feature(FEATURE_VBAT) || feature(FEATURE_CURRENT_METER)); setTaskEnabled(TASK_RX, true); #ifdef GPS setTaskEnabled(TASK_GPS, feature(FEATURE_GPS)); #endif #ifdef MAG setTaskEnabled(TASK_COMPASS, sensors(SENSOR_MAG)); #if defined(USE_SPI) && defined(USE_MAG_AK8963) // fixme temporary solution for AK6983 via slave I2C on MPU9250 rescheduleTask(TASK_COMPASS, 1000000 / 40); #endif #endif #ifdef BARO setTaskEnabled(TASK_BARO, sensors(SENSOR_BARO)); #endif #ifdef SONAR setTaskEnabled(TASK_SONAR, sensors(SENSOR_SONAR)); #endif #if defined(BARO) || defined(SONAR) setTaskEnabled(TASK_ALTITUDE, sensors(SENSOR_BARO) || sensors(SENSOR_SONAR)); #endif #ifdef DISPLAY setTaskEnabled(TASK_DISPLAY, feature(FEATURE_DISPLAY)); #endif #ifdef TELEMETRY setTaskEnabled(TASK_TELEMETRY, feature(FEATURE_TELEMETRY)); // Reschedule telemetry to 500hz for Jeti Exbus if (feature(FEATURE_TELEMETRY) || masterConfig.rxConfig.serialrx_provider == SERIALRX_JETIEXBUS) rescheduleTask(TASK_TELEMETRY, 2000); #endif #ifdef LED_STRIP setTaskEnabled(TASK_LEDSTRIP, feature(FEATURE_LED_STRIP)); #endif #ifdef TRANSPONDER setTaskEnabled(TASK_TRANSPONDER, feature(FEATURE_TRANSPONDER)); #endif #ifdef OSD setTaskEnabled(TASK_OSD, feature(FEATURE_OSD)); #endif #ifdef USE_BST setTaskEnabled(TASK_BST_MASTER_PROCESS, true); #endif }
void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_SERIAL | FEATURE_RX_MSP); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM); } #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_UART3) if (doesConfigurationUsePort(SERIAL_PORT_UART3) && featureConfigured(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif #ifdef STM32F303xC // hardware supports serial port inversion, make users life easier for those that want to connect SBus RX's #ifdef TELEMETRY masterConfig.telemetryConfig.telemetry_inversion = 1; #endif #endif /* * The retarded_arm setting is incompatible with pid_at_min_throttle because full roll causes the craft to roll over on the ground. * The pid_at_min_throttle implementation ignores yaw on the ground, but doesn't currently ignore roll when retarded_arm is enabled. */ if (masterConfig.retarded_arm && masterConfig.mixerConfig.pid_at_min_throttle) { masterConfig.mixerConfig.pid_at_min_throttle = 0; } #if defined(LED_STRIP) && defined(TRANSPONDER) && !defined(UNIT_TEST) if ((WS2811_DMA_TC_FLAG == TRANSPONDER_DMA_TC_FLAG) && featureConfigured(FEATURE_TRANSPONDER) && featureConfigured(FEATURE_LED_STRIP)) { featureClear(FEATURE_LED_STRIP); } #endif #if defined(CC3D) && defined(SONAR) && defined(USE_SOFTSERIAL1) if (featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_SOFTSERIAL)) { featureClear(FEATURE_SONAR); } #endif #if defined(COLIBRI_RACE) masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; if(featureConfigured(FEATURE_RX_SERIAL)) { masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL; } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } }
static void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP) || featureConfigured(FEATURE_RX_NRF24))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_NRF24); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_NRF24); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_NRF24); } if (featureConfigured(FEATURE_RX_NRF24)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_MSP); } #if defined(NAV) // Ensure sane values of navConfig settings validateNavConfig(&masterConfig.navConfig); #endif if (featureConfigured(FEATURE_SOFTSPI)) { featureClear(FEATURE_RX_PPM | FEATURE_RX_PARALLEL_PWM | FEATURE_SOFTSERIAL | FEATURE_VBAT); #if defined(STM32F10X) featureClear(FEATURE_LED_STRIP); // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_NRF24); #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #if defined(CC3D) // There is a timer clash between PWM RX pins and motor output pins - this forces us to have same timer tick rate for these timers // which is only possible when using brushless motors w/o oneshot (timer tick rate is PWM_TIMER_MHZ) // On CC3D OneShot is incompatible with PWM RX featureClear(FEATURE_ONESHOT125); // Brushed motors on CC3D are not possible when using PWM RX if (masterConfig.motor_pwm_rate > BRUSHLESS_MOTORS_PWM_RATE) { masterConfig.motor_pwm_rate = BRUSHLESS_MOTORS_PWM_RATE; } #endif #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #ifdef STM32F10X // avoid overloading the CPU on F1 targets when using gyro sync and GPS. if (masterConfig.gyroSync && masterConfig.gyroSyncDenominator < 2 && featureConfigured(FEATURE_GPS)) { masterConfig.gyroSyncDenominator = 2; } // avoid overloading the CPU when looptime < 2000 and GPS if (masterConfig.looptime && featureConfigured(FEATURE_GPS)) { masterConfig.looptime = 2000; } #endif #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (WS2811_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (WS2811_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(NAZE) && defined(SONAR) if (featureConfigured(FEATURE_RX_PARALLEL_PWM) && featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_USART3) if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif #ifdef STM32F303xC // hardware supports serial port inversion, make users life easier for those that want to connect SBus RX's #ifdef TELEMETRY masterConfig.telemetryConfig.telemetry_inversion = 1; #endif #endif #if defined(CC3D) #if defined(CC3D_PPM1) #if defined(SONAR) && defined(USE_SOFTSERIAL1) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { featureClear(FEATURE_SONAR); } #endif #else #if defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #endif // CC3D_PPM1 #endif // CC3D #if defined(COLIBRI_RACE) masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; if(featureConfigured(FEATURE_RX_SERIAL)) { masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL; } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } /* * If provided predefined mixer setup is disabled, fallback to default one */ if (!isMixerEnabled(masterConfig.mixerMode)) { masterConfig.mixerMode = DEFAULT_MIXER; } }
void rxInit(const rxConfig_t *rxConfig, const modeActivationCondition_t *modeActivationConditions) { uint8_t i; uint16_t value; useRxConfig(rxConfig); rxRuntimeConfig.rcReadRawFn = nullReadRawRC; rxRuntimeConfig.rcFrameStatusFn = nullFrameStatus; rcSampleIndex = 0; for (i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) { rcData[i] = rxConfig->midrc; rcInvalidPulsPeriod[i] = millis() + MAX_INVALID_PULS_TIME; } rcData[THROTTLE] = (feature(FEATURE_3D)) ? rxConfig->midrc : rxConfig->rx_min_usec; // Initialize ARM switch to OFF position when arming via switch is defined for (i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) { const modeActivationCondition_t *modeActivationCondition = &modeActivationConditions[i]; if (modeActivationCondition->modeId == BOXARM && IS_RANGE_USABLE(&modeActivationCondition->range)) { // ARM switch is defined, determine an OFF value if (modeActivationCondition->range.startStep > 0) { value = MODE_STEP_TO_CHANNEL_VALUE((modeActivationCondition->range.startStep - 1)); } else { value = MODE_STEP_TO_CHANNEL_VALUE((modeActivationCondition->range.endStep + 1)); } // Initialize ARM AUX channel to OFF value rcData[modeActivationCondition->auxChannelIndex + NON_AUX_CHANNEL_COUNT] = value; } } #ifdef SERIAL_RX if (feature(FEATURE_RX_SERIAL)) { serialRxInit(rxConfig, &rxRuntimeConfig); } #endif #ifndef SKIP_RX_MSP if (feature(FEATURE_RX_MSP)) { rxMspInit(rxConfig, &rxRuntimeConfig); } #endif #ifdef USE_RX_SPI if (feature(FEATURE_RX_SPI)) { const bool enabled = rxSpiInit(rxConfig, &rxRuntimeConfig); if (!enabled) { featureClear(FEATURE_RX_SPI); rxRuntimeConfig.rcReadRawFn = nullReadRawRC; } } #endif #ifndef SKIP_RX_PWM_PPM if (feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM)) { rxRuntimeConfig.rxRefreshRate = 20000; rxPwmInit(rxConfig, &rxRuntimeConfig); } #endif }
static void validateAndFixConfig(void) { #if !defined(USE_QUAD_MIXER_ONLY) && !defined(USE_OSD_SLAVE) // Reset unsupported mixer mode to default. // This check will be gone when motor/servo mixers are loaded dynamically // by configurator as a part of configuration procedure. mixerMode_e mixerMode = mixerConfigMutable()->mixerMode; if (!(mixerMode == MIXER_CUSTOM || mixerMode == MIXER_CUSTOM_AIRPLANE || mixerMode == MIXER_CUSTOM_TRI)) { if (mixers[mixerMode].motorCount && mixers[mixerMode].motor == NULL) mixerConfigMutable()->mixerMode = MIXER_CUSTOM; #ifdef USE_SERVOS if (mixers[mixerMode].useServo && servoMixers[mixerMode].servoRuleCount == 0) mixerConfigMutable()->mixerMode = MIXER_CUSTOM_AIRPLANE; #endif } #endif #ifndef USE_OSD_SLAVE if (systemConfig()->activeRateProfile >= CONTROL_RATE_PROFILE_COUNT) { systemConfigMutable()->activeRateProfile = 0; } setControlRateProfile(systemConfig()->activeRateProfile); if (systemConfig()->pidProfileIndex >= MAX_PROFILE_COUNT) { systemConfigMutable()->pidProfileIndex = 0; } setPidProfile(systemConfig()->pidProfileIndex); // Prevent invalid notch cutoff if (currentPidProfile->dterm_notch_cutoff >= currentPidProfile->dterm_notch_hz) { currentPidProfile->dterm_notch_hz = 0; } if ((motorConfig()->dev.motorPwmProtocol == PWM_TYPE_BRUSHED) && (motorConfig()->mincommand < 1000)) { motorConfigMutable()->mincommand = 1000; } if ((motorConfig()->dev.motorPwmProtocol == PWM_TYPE_STANDARD) && (motorConfig()->dev.motorPwmRate > BRUSHLESS_MOTORS_PWM_RATE)) { motorConfigMutable()->dev.motorPwmRate = BRUSHLESS_MOTORS_PWM_RATE; } validateAndFixGyroConfig(); if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP) || featureConfigured(FEATURE_RX_SPI))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_SPI); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_SPI); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_SPI); } #ifdef USE_RX_SPI if (featureConfigured(FEATURE_RX_SPI)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_PARALLEL_PWM | FEATURE_RX_PPM | FEATURE_RX_MSP); } #endif // USE_RX_SPI if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { featureClear(FEATURE_RX_SERIAL | FEATURE_RX_MSP | FEATURE_RX_PPM | FEATURE_RX_SPI); #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (batteryConfig()->currentMeterSource == CURRENT_METER_ADC) { batteryConfigMutable()->currentMeterSource = CURRENT_METER_NONE; } #endif // STM32F10X // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #ifdef USE_SOFTSPI if (featureConfigured(FEATURE_SOFTSPI)) { featureClear(FEATURE_RX_PPM | FEATURE_RX_PARALLEL_PWM | FEATURE_SOFTSERIAL); batteryConfigMutable()->voltageMeterSource = VOLTAGE_METER_NONE; #if defined(STM32F10X) featureClear(FEATURE_LED_STRIP); // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (batteryConfig()->currentMeterSource == CURRENT_METER_ADC) { batteryConfigMutable()->currentMeterSource = CURRENT_METER_NONE; } #endif // STM32F10X } #endif // USE_SOFTSPI #endif // USE_OSD_SLAVE if (!isSerialConfigValid(serialConfig())) { pgResetFn_serialConfig(serialConfigMutable()); } // clear features that are not supported. // I have kept them all here in one place, some could be moved to sections of code above. #ifndef USE_PPM featureClear(FEATURE_RX_PPM); #endif #ifndef USE_SERIAL_RX featureClear(FEATURE_RX_SERIAL); #endif #if !defined(USE_SOFTSERIAL1) && !defined(USE_SOFTSERIAL2) featureClear(FEATURE_SOFTSERIAL); #endif #ifndef USE_GPS featureClear(FEATURE_GPS); #endif #ifndef USE_RANGEFINDER featureClear(FEATURE_RANGEFINDER); #endif #ifndef USE_TELEMETRY featureClear(FEATURE_TELEMETRY); #endif #ifndef USE_PWM featureClear(FEATURE_RX_PARALLEL_PWM); #endif #ifndef USE_RX_MSP featureClear(FEATURE_RX_MSP); #endif #ifndef USE_LED_STRIP featureClear(FEATURE_LED_STRIP); #endif #ifndef USE_DASHBOARD featureClear(FEATURE_DASHBOARD); #endif #ifndef USE_OSD featureClear(FEATURE_OSD); #endif #ifndef USE_SERVOS featureClear(FEATURE_SERVO_TILT | FEATURE_CHANNEL_FORWARDING); #endif #ifndef USE_TRANSPONDER featureClear(FEATURE_TRANSPONDER); #endif #ifndef USE_RX_SPI featureClear(FEATURE_RX_SPI); #endif #ifndef USE_SOFTSPI featureClear(FEATURE_SOFTSPI); #endif #ifndef USE_ESC_SENSOR featureClear(FEATURE_ESC_SENSOR); #endif #ifndef USE_GYRO_DATA_ANALYSE featureClear(FEATURE_DYNAMIC_FILTER); #endif #if defined(TARGET_VALIDATECONFIG) targetValidateConfiguration(); #endif }
void init(void) { #ifdef USE_HAL_DRIVER HAL_Init(); #endif printfSupportInit(); initEEPROM(); ensureEEPROMContainsValidData(); readEEPROM(); systemState |= SYSTEM_STATE_CONFIG_LOADED; systemInit(); //i2cSetOverclock(masterConfig.i2c_overclock); // initialize IO (needed for all IO operations) IOInitGlobal(); debugMode = masterConfig.debug_mode; #ifdef USE_HARDWARE_REVISION_DETECTION detectHardwareRevision(); #endif // Latch active features to be used for feature() in the remainder of init(). latchActiveFeatures(); #ifdef ALIENFLIGHTF3 ledInit(hardwareRevision == AFF3_REV_1 ? false : true); #else ledInit(false); #endif LED2_ON; #ifdef USE_EXTI EXTIInit(); #endif #if defined(BUTTONS) gpio_config_t buttonAGpioConfig = { BUTTON_A_PIN, Mode_IPU, Speed_2MHz }; gpioInit(BUTTON_A_PORT, &buttonAGpioConfig); gpio_config_t buttonBGpioConfig = { BUTTON_B_PIN, Mode_IPU, Speed_2MHz }; gpioInit(BUTTON_B_PORT, &buttonBGpioConfig); // Check status of bind plug and exit if not active delayMicroseconds(10); // allow GPIO configuration to settle if (!isMPUSoftReset()) { uint8_t secondsRemaining = 5; bool bothButtonsHeld; do { bothButtonsHeld = !digitalIn(BUTTON_A_PORT, BUTTON_A_PIN) && !digitalIn(BUTTON_B_PORT, BUTTON_B_PIN); if (bothButtonsHeld) { if (--secondsRemaining == 0) { resetEEPROM(); systemReset(); } delay(1000); LED0_TOGGLE; } } while (bothButtonsHeld); } #endif #ifdef SPEKTRUM_BIND if (feature(FEATURE_RX_SERIAL)) { switch (masterConfig.rxConfig.serialrx_provider) { case SERIALRX_SPEKTRUM1024: case SERIALRX_SPEKTRUM2048: // Spektrum satellite binding if enabled on startup. // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup. // The rest of Spektrum initialization will happen later - via spektrumInit() spektrumBind(&masterConfig.rxConfig); break; } } #endif delay(100); timerInit(); // timer must be initialized before any channel is allocated #if !defined(USE_HAL_DRIVER) dmaInit(); #endif #if defined(AVOID_UART1_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART1 : SERIAL_PORT_NONE); #elif defined(AVOID_UART2_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART2 : SERIAL_PORT_NONE); #elif defined(AVOID_UART3_FOR_PWM_PPM) serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), feature(FEATURE_RX_PPM) || feature(FEATURE_RX_PARALLEL_PWM) ? SERIAL_PORT_USART3 : SERIAL_PORT_NONE); #else serialInit(&masterConfig.serialConfig, feature(FEATURE_SOFTSERIAL), SERIAL_PORT_NONE); #endif mixerInit(masterConfig.mixerMode, masterConfig.customMotorMixer); #ifdef USE_SERVOS servoMixerInit(masterConfig.customServoMixer); #endif uint16_t idlePulse = masterConfig.motorConfig.mincommand; if (feature(FEATURE_3D)) { idlePulse = masterConfig.flight3DConfig.neutral3d; } if (masterConfig.motorConfig.motorPwmProtocol == PWM_TYPE_BRUSHED) { featureClear(FEATURE_3D); idlePulse = 0; // brushed motors } #ifdef USE_QUAD_MIXER_ONLY motorInit(&masterConfig.motorConfig, idlePulse, QUAD_MOTOR_COUNT); #else motorInit(&masterConfig.motorConfig, idlePulse, mixers[masterConfig.mixerMode].motorCount); #endif #ifdef USE_SERVOS if (isMixerUsingServos()) { //pwm_params.useChannelForwarding = feature(FEATURE_CHANNEL_FORWARDING); servoInit(&masterConfig.servoConfig); } #endif #ifndef SKIP_RX_PWM_PPM if (feature(FEATURE_RX_PPM)) { ppmRxInit(&masterConfig.ppmConfig, masterConfig.motorConfig.motorPwmProtocol); } else if (feature(FEATURE_RX_PARALLEL_PWM)) { pwmRxInit(&masterConfig.pwmConfig); } pwmRxSetInputFilteringMode(masterConfig.inputFilteringMode); #endif mixerConfigureOutput(); #ifdef USE_SERVOS servoConfigureOutput(); #endif systemState |= SYSTEM_STATE_MOTORS_READY; #ifdef BEEPER beeperInit(&masterConfig.beeperConfig); #endif /* temp until PGs are implemented. */ #ifdef INVERTER initInverter(); #endif #ifdef USE_BST bstInit(BST_DEVICE); #endif #ifdef USE_SPI #ifdef USE_SPI_DEVICE_1 spiInit(SPIDEV_1); #endif #ifdef USE_SPI_DEVICE_2 spiInit(SPIDEV_2); #endif #ifdef USE_SPI_DEVICE_3 #ifdef ALIENFLIGHTF3 if (hardwareRevision == AFF3_REV_2) { spiInit(SPIDEV_3); } #else spiInit(SPIDEV_3); #endif #endif #ifdef USE_SPI_DEVICE_4 spiInit(SPIDEV_4); #endif #endif #ifdef VTX vtxInit(); #endif #ifdef USE_HARDWARE_REVISION_DETECTION updateHardwareRevision(); #endif #if defined(NAZE) if (hardwareRevision == NAZE32_SP) { serialRemovePort(SERIAL_PORT_SOFTSERIAL2); } else { serialRemovePort(SERIAL_PORT_USART3); } #endif #if defined(SPRACINGF3) && defined(SONAR) && defined(USE_SOFTSERIAL2) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { serialRemovePort(SERIAL_PORT_SOFTSERIAL2); } #endif #if defined(SPRACINGF3MINI) || defined(OMNIBUS) || defined(X_RACERSPI) #if defined(SONAR) && defined(USE_SOFTSERIAL1) if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) { serialRemovePort(SERIAL_PORT_SOFTSERIAL1); } #endif #endif #ifdef USE_I2C #if defined(NAZE) if (hardwareRevision != NAZE32_SP) { i2cInit(I2C_DEVICE); } else { if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { i2cInit(I2C_DEVICE); } } #elif defined(CC3D) if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) { i2cInit(I2C_DEVICE); } #else i2cInit(I2C_DEVICE); #endif #endif #ifdef USE_ADC drv_adc_config_t adc_params; adc_params.enableVBat = feature(FEATURE_VBAT); adc_params.enableRSSI = feature(FEATURE_RSSI_ADC); adc_params.enableCurrentMeter = feature(FEATURE_CURRENT_METER); adc_params.enableExternal1 = false; #ifdef OLIMEXINO adc_params.enableExternal1 = true; #endif #ifdef NAZE // optional ADC5 input on rev.5 hardware adc_params.enableExternal1 = (hardwareRevision >= NAZE32_REV5); #endif adcInit(&adc_params); #endif initBoardAlignment(&masterConfig.boardAlignment); #ifdef DISPLAY if (feature(FEATURE_DISPLAY)) { displayInit(&masterConfig.rxConfig); } #endif #ifdef USE_RTC6705 if (feature(FEATURE_VTX)) { rtc6705_soft_spi_init(); current_vtx_channel = masterConfig.vtx_channel; rtc6705_soft_spi_set_channel(vtx_freq[current_vtx_channel]); rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power); } #endif #ifdef OSD if (feature(FEATURE_OSD)) { osdInit(); } #endif if (!sensorsAutodetect(&masterConfig.sensorAlignmentConfig, masterConfig.acc_hardware, masterConfig.mag_hardware, masterConfig.baro_hardware, masterConfig.mag_declination, masterConfig.gyro_lpf, masterConfig.gyro_sync_denom)) { // if gyro was not detected due to whatever reason, we give up now. failureMode(FAILURE_MISSING_ACC); } systemState |= SYSTEM_STATE_SENSORS_READY; LED1_ON; LED0_OFF; LED2_OFF; for (int i = 0; i < 10; i++) { LED1_TOGGLE; LED0_TOGGLE; delay(25); if (!(getBeeperOffMask() & (1 << (BEEPER_SYSTEM_INIT - 1)))) BEEP_ON; delay(25); BEEP_OFF; } LED0_OFF; LED1_OFF; #ifdef MAG if (sensors(SENSOR_MAG)) compassInit(); #endif imuInit(); mspFcInit(); mspSerialInit(); #ifdef USE_CLI cliInit(&masterConfig.serialConfig); #endif failsafeInit(&masterConfig.rxConfig, masterConfig.flight3DConfig.deadband3d_throttle); rxInit(&masterConfig.rxConfig, masterConfig.modeActivationConditions); #ifdef GPS if (feature(FEATURE_GPS)) { gpsInit( &masterConfig.serialConfig, &masterConfig.gpsConfig ); navigationInit( &masterConfig.gpsProfile, ¤tProfile->pidProfile ); } #endif #ifdef SONAR if (feature(FEATURE_SONAR)) { sonarInit(&masterConfig.sonarConfig); } #endif #ifdef LED_STRIP ledStripInit(masterConfig.ledConfigs, masterConfig.colors, masterConfig.modeColors, &masterConfig.specialColors); if (feature(FEATURE_LED_STRIP)) { ledStripEnable(); } #endif #ifdef TELEMETRY if (feature(FEATURE_TELEMETRY)) { telemetryInit(); } #endif #ifdef USB_CABLE_DETECTION usbCableDetectInit(); #endif #ifdef TRANSPONDER if (feature(FEATURE_TRANSPONDER)) { transponderInit(masterConfig.transponderData); transponderEnable(); transponderStartRepeating(); systemState |= SYSTEM_STATE_TRANSPONDER_ENABLED; } #endif #ifdef USE_FLASHFS #ifdef NAZE if (hardwareRevision == NAZE32_REV5) { m25p16_init(IO_TAG_NONE); } #elif defined(USE_FLASH_M25P16) m25p16_init(IO_TAG_NONE); #endif flashfsInit(); #endif #ifdef USE_SDCARD bool sdcardUseDMA = false; sdcardInsertionDetectInit(); #ifdef SDCARD_DMA_CHANNEL_TX #if defined(LED_STRIP) && defined(WS2811_DMA_CHANNEL) // Ensure the SPI Tx DMA doesn't overlap with the led strip #if defined(STM32F4) || defined(STM32F7) sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_STREAM; #else sdcardUseDMA = !feature(FEATURE_LED_STRIP) || SDCARD_DMA_CHANNEL_TX != WS2811_DMA_CHANNEL; #endif #else sdcardUseDMA = true; #endif #endif sdcard_init(sdcardUseDMA); afatfs_init(); #endif if (masterConfig.gyro_lpf > 0 && masterConfig.gyro_lpf < 7) { masterConfig.pid_process_denom = 1; // When gyro set to 1khz always set pid speed 1:1 to sampling speed masterConfig.gyro_sync_denom = 1; } setTargetPidLooptime((gyro.targetLooptime + LOOPTIME_SUSPEND_TIME) * masterConfig.pid_process_denom); // Initialize pid looptime #ifdef BLACKBOX initBlackbox(); #endif if (masterConfig.mixerMode == MIXER_GIMBAL) { accSetCalibrationCycles(CALIBRATING_ACC_CYCLES); } gyroSetCalibrationCycles(); #ifdef BARO baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES); #endif // start all timers // TODO - not implemented yet timerStart(); ENABLE_STATE(SMALL_ANGLE); DISABLE_ARMING_FLAG(PREVENT_ARMING); #ifdef SOFTSERIAL_LOOPBACK // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly loopbackPort = (serialPort_t*)&(softSerialPorts[0]); if (!loopbackPort->vTable) { loopbackPort = openSoftSerial(0, NULL, 19200, SERIAL_NOT_INVERTED); } serialPrint(loopbackPort, "LOOPBACK\r\n"); #endif // Now that everything has powered up the voltage and cell count be determined. if (feature(FEATURE_VBAT | FEATURE_CURRENT_METER)) batteryInit(&masterConfig.batteryConfig); #ifdef DISPLAY if (feature(FEATURE_DISPLAY)) { #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY displayShowFixedPage(PAGE_GPS); #else displayResetPageCycling(); displayEnablePageCycling(); #endif } #endif #ifdef CJMCU LED2_ON; #endif // Latch active features AGAIN since some may be modified by init(). latchActiveFeatures(); motorControlEnable = true; fcTasksInit(); systemState |= SYSTEM_STATE_READY; }
void validateAndFixConfig(void) { if (!(feature(FEATURE_RX_PARALLEL_PWM) || feature(FEATURE_RX_PPM) || feature(FEATURE_RX_SERIAL) || feature(FEATURE_RX_MSP))) { featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM } if (feature(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM); } if (feature(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL); featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_PARALLEL_PWM)) { #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports featureClear(FEATURE_CURRENT_METER); #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (feature(FEATURE_SOFTSERIAL) && ( #ifdef USE_SOFTSERIAL1 (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #else 0 #endif || #ifdef USE_SOFTSERIAL2 (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #else 0 #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(NAZE) && defined(SONAR) if (feature(FEATURE_RX_PARALLEL_PWM) && feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER)) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER)) { featureClear(FEATURE_CURRENT_METER); } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; applySerialConfigToPortFunctions(serialConfig); if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } }
void validateAndFixConfig(void) { if (!(feature(FEATURE_RX_PARALLEL_PWM) || feature(FEATURE_RX_PPM) || feature(FEATURE_RX_SERIAL) || feature(FEATURE_RX_MSP))) { featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM } if (feature(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM); } if (feature(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL); featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (feature(FEATURE_RX_PARALLEL_PWM)) { #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (feature(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(NAZE) && defined(SONAR) if (feature(FEATURE_RX_PARALLEL_PWM) && feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_USART3) if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif /* * The retarded_arm setting is incompatible with pid_at_min_throttle because full roll causes the craft to roll over on the ground. * The pid_at_min_throttle implementation ignores yaw on the ground, but doesn't currently ignore roll when retarded_arm is enabled. */ if (masterConfig.retarded_arm && masterConfig.mixerConfig.pid_at_min_throttle) { masterConfig.mixerConfig.pid_at_min_throttle = 0; } useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } }
// Default settings static void resetConf(void) { int i; int8_t servoRates[8] = { 30, 30, 100, 100, 100, 100, 100, 100 }; // Clear all configuration memset(&masterConfig, 0, sizeof(master_t)); setProfile(0); setControlRateProfile(0); masterConfig.version = EEPROM_CONF_VERSION; masterConfig.mixerMode = MIXER_QUADX; featureClearAll(); #if defined(CJMCU) || defined(SPARKY) featureSet(FEATURE_RX_PPM); #endif featureSet(FEATURE_VBAT); // global settings masterConfig.current_profile_index = 0; // default profile masterConfig.gyro_cmpf_factor = 600; // default MWC masterConfig.gyro_cmpfm_factor = 250; // default MWC masterConfig.gyro_lpf = 42; // supported by all gyro drivers now. In case of ST gyro, will default to 32Hz instead resetAccelerometerTrims(&masterConfig.accZero); resetSensorAlignment(&masterConfig.sensorAlignmentConfig); masterConfig.boardAlignment.rollDegrees = 0; masterConfig.boardAlignment.pitchDegrees = 0; masterConfig.boardAlignment.yawDegrees = 0; masterConfig.acc_hardware = ACC_DEFAULT; // default/autodetect masterConfig.max_angle_inclination = 500; // 50 degrees masterConfig.yaw_control_direction = 1; masterConfig.gyroConfig.gyroMovementCalibrationThreshold = 32; masterConfig.mag_hardware = MAG_DEFAULT; // default/autodetect resetBatteryConfig(&masterConfig.batteryConfig); resetTelemetryConfig(&masterConfig.telemetryConfig); masterConfig.rxConfig.serialrx_provider = 0; masterConfig.rxConfig.spektrum_sat_bind = 0; masterConfig.rxConfig.midrc = 1500; masterConfig.rxConfig.mincheck = 1100; masterConfig.rxConfig.maxcheck = 1900; masterConfig.rxConfig.rssi_channel = 0; masterConfig.rxConfig.rssi_scale = RSSI_SCALE_DEFAULT; masterConfig.inputFilteringMode = INPUT_FILTERING_DISABLED; masterConfig.retarded_arm = 0; masterConfig.disarm_kill_switch = 1; masterConfig.auto_disarm_delay = 5; masterConfig.small_angle = 25; masterConfig.airplaneConfig.flaps_speed = 0; masterConfig.airplaneConfig.fixedwing_althold_dir = 1; // Motor/ESC/Servo resetEscAndServoConfig(&masterConfig.escAndServoConfig); resetFlight3DConfig(&masterConfig.flight3DConfig); #ifdef BRUSHED_MOTORS masterConfig.motor_pwm_rate = BRUSHED_MOTORS_PWM_RATE; #else masterConfig.motor_pwm_rate = BRUSHLESS_MOTORS_PWM_RATE; #endif masterConfig.servo_pwm_rate = 50; #ifdef GPS // gps/nav stuff masterConfig.gpsConfig.provider = GPS_NMEA; masterConfig.gpsConfig.sbasMode = SBAS_AUTO; masterConfig.gpsConfig.autoConfig = GPS_AUTOCONFIG_ON; masterConfig.gpsConfig.autoBaud = GPS_AUTOBAUD_OFF; #endif resetSerialConfig(&masterConfig.serialConfig); masterConfig.looptime = 3500; masterConfig.emf_avoidance = 0; resetPidProfile(¤tProfile->pidProfile); resetControlRateConfig(&masterConfig.controlRateProfiles[0]); // for (i = 0; i < CHECKBOXITEMS; i++) // cfg.activate[i] = 0; resetRollAndPitchTrims(¤tProfile->accelerometerTrims); currentProfile->mag_declination = 0; currentProfile->acc_lpf_factor = 4; currentProfile->accz_lpf_cutoff = 5.0f; currentProfile->accDeadband.xy = 40; currentProfile->accDeadband.z = 40; resetBarometerConfig(¤tProfile->barometerConfig); currentProfile->acc_unarmedcal = 1; // Radio parseRcChannels("AETR1234", &masterConfig.rxConfig); resetRcControlsConfig(¤tProfile->rcControlsConfig); currentProfile->throttle_correction_value = 0; // could 10 with althold or 40 for fpv currentProfile->throttle_correction_angle = 800; // could be 80.0 deg with atlhold or 45.0 for fpv // Failsafe Variables currentProfile->failsafeConfig.failsafe_delay = 10; // 1sec currentProfile->failsafeConfig.failsafe_off_delay = 200; // 20sec currentProfile->failsafeConfig.failsafe_throttle = 1200; // decent default which should always be below hover throttle for people. currentProfile->failsafeConfig.failsafe_min_usec = 985; // any of first 4 channels below this value will trigger failsafe currentProfile->failsafeConfig.failsafe_max_usec = 2115; // any of first 4 channels above this value will trigger failsafe // servos for (i = 0; i < 8; i++) { currentProfile->servoConf[i].min = DEFAULT_SERVO_MIN; currentProfile->servoConf[i].max = DEFAULT_SERVO_MAX; currentProfile->servoConf[i].middle = DEFAULT_SERVO_MIDDLE; currentProfile->servoConf[i].rate = servoRates[i]; currentProfile->servoConf[i].forwardFromChannel = CHANNEL_FORWARDING_DISABLED; } currentProfile->mixerConfig.yaw_direction = 1; currentProfile->mixerConfig.tri_unarmed_servo = 1; // gimbal currentProfile->gimbalConfig.gimbal_flags = GIMBAL_NORMAL; #ifdef GPS resetGpsProfile(¤tProfile->gpsProfile); #endif // custom mixer. clear by defaults. for (i = 0; i < MAX_SUPPORTED_MOTORS; i++) masterConfig.customMixer[i].throttle = 0.0f; #ifdef LED_STRIP applyDefaultColors(masterConfig.colors, CONFIGURABLE_COLOR_COUNT); applyDefaultLedStripConfig(masterConfig.ledConfigs); #endif #ifdef BLACKBOX masterConfig.blackbox_rate_num = 1; masterConfig.blackbox_rate_denom = 1; #endif // alternative defaults settings for ALIENWIIF1 and ALIENWIIF3 targets #ifdef ALIENWII32 featureSet(FEATURE_RX_SERIAL); featureSet(FEATURE_MOTOR_STOP); featureSet(FEATURE_FAILSAFE); featureClear(FEATURE_VBAT); #ifdef ALIENWIIF3 masterConfig.serialConfig.serial_port_scenario[2] = lookupScenarioIndex(SCENARIO_SERIAL_RX_ONLY); #else masterConfig.serialConfig.serial_port_scenario[1] = lookupScenarioIndex(SCENARIO_SERIAL_RX_ONLY); #endif masterConfig.rxConfig.serialrx_provider = 1; masterConfig.rxConfig.spektrum_sat_bind = 5; masterConfig.escAndServoConfig.minthrottle = 1000; masterConfig.escAndServoConfig.maxthrottle = 2000; masterConfig.motor_pwm_rate = 32000; masterConfig.looptime = 2000; currentProfile->pidProfile.pidController = 3; currentProfile->pidProfile.P8[ROLL] = 36; currentProfile->pidProfile.P8[PITCH] = 36; currentProfile->failsafeConfig.failsafe_delay = 2; currentProfile->failsafeConfig.failsafe_off_delay = 0; currentProfile->failsafeConfig.failsafe_throttle = 1000; currentControlRateProfile->rcRate8 = 130; currentControlRateProfile->rollPitchRate = 20; currentControlRateProfile->yawRate = 60; currentControlRateProfile->yawRate = 100; parseRcChannels("TAER1234", &masterConfig.rxConfig); // { 1.0f, -0.5f, 1.0f, -1.0f }, // REAR_R masterConfig.customMixer[0].throttle = 1.0f; masterConfig.customMixer[0].roll = -0.5f; masterConfig.customMixer[0].pitch = 1.0f; masterConfig.customMixer[0].yaw = -1.0f; // { 1.0f, -0.5f, -1.0f, 1.0f }, // FRONT_R masterConfig.customMixer[1].throttle = 1.0f; masterConfig.customMixer[1].roll = -0.5f; masterConfig.customMixer[1].pitch = -1.0f; masterConfig.customMixer[1].yaw = 1.0f; // { 1.0f, 0.5f, 1.0f, 1.0f }, // REAR_L masterConfig.customMixer[2].throttle = 1.0f; masterConfig.customMixer[2].roll = 0.5f; masterConfig.customMixer[2].pitch = 1.0f; masterConfig.customMixer[2].yaw = 1.0f; // { 1.0f, 0.5f, -1.0f, -1.0f }, // FRONT_L masterConfig.customMixer[3].throttle = 1.0f; masterConfig.customMixer[3].roll = 0.5f; masterConfig.customMixer[3].pitch = -1.0f; masterConfig.customMixer[3].yaw = -1.0f; // { 1.0f, -1.0f, -0.5f, -1.0f }, // MIDFRONT_R masterConfig.customMixer[4].throttle = 1.0f; masterConfig.customMixer[4].roll = -1.0f; masterConfig.customMixer[4].pitch = -0.5f; masterConfig.customMixer[4].yaw = -1.0f; // { 1.0f, 1.0f, -0.5f, 1.0f }, // MIDFRONT_L masterConfig.customMixer[5].throttle = 1.0f; masterConfig.customMixer[5].roll = 1.0f; masterConfig.customMixer[5].pitch = -0.5f; masterConfig.customMixer[5].yaw = 1.0f; // { 1.0f, -1.0f, 0.5f, 1.0f }, // MIDREAR_R masterConfig.customMixer[6].throttle = 1.0f; masterConfig.customMixer[6].roll = -1.0f; masterConfig.customMixer[6].pitch = 0.5f; masterConfig.customMixer[6].yaw = 1.0f; // { 1.0f, 1.0f, 0.5f, -1.0f }, // MIDREAR_L masterConfig.customMixer[7].throttle = 1.0f; masterConfig.customMixer[7].roll = 1.0f; masterConfig.customMixer[7].pitch = 0.5f; masterConfig.customMixer[7].yaw = -1.0f; #endif // copy first profile into remaining profile for (i = 1; i < MAX_PROFILE_COUNT; i++) { memcpy(&masterConfig.profile[i], currentProfile, sizeof(profile_t)); } // copy first control rate config into remaining profile for (i = 1; i < MAX_CONTROL_RATE_PROFILE_COUNT; i++) { memcpy(&masterConfig.controlRateProfiles[i], currentControlRateProfile, sizeof(controlRateConfig_t)); } for (i = 1; i < MAX_PROFILE_COUNT; i++) { masterConfig.profile[i].defaultRateProfileIndex = i % MAX_CONTROL_RATE_PROFILE_COUNT; } }
void validateAndFixConfig(void) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { featureSet(DEFAULT_RX_FEATURE); } if (featureConfigured(FEATURE_RX_PPM)) { featureClear(FEATURE_RX_PARALLEL_PWM); } if (featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_SERIAL); featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_SERIAL)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PPM); } if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) { #if defined(STM32F10X) // rssi adc needs the same ports featureClear(FEATURE_RSSI_ADC); // current meter needs the same ports if (masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(STM32F10X) || defined(CHEBUZZ) || defined(STM32F3DISCOVERY) // led strip needs the same ports featureClear(FEATURE_LED_STRIP); #endif // software serial needs free PWM ports featureClear(FEATURE_SOFTSERIAL); } #if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2)) if (featureConfigured(FEATURE_SOFTSERIAL) && ( 0 #ifdef USE_SOFTSERIAL1 || (WS2811_TIMER == SOFTSERIAL_1_TIMER) #endif #ifdef USE_SOFTSERIAL2 || (WS2811_TIMER == SOFTSERIAL_2_TIMER) #endif )) { // led strip needs the same timer as softserial featureClear(FEATURE_LED_STRIP); } #endif #if defined(NAZE) && defined(SONAR) if (featureConfigured(FEATURE_RX_PARALLEL_PWM) && featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(OLIMEXINO) && defined(SONAR) if (feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) { featureClear(FEATURE_CURRENT_METER); } #endif #if defined(CC3D) && defined(DISPLAY) && defined(USE_UART3) if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) { featureClear(FEATURE_DISPLAY); } #endif /*#if defined(LED_STRIP) && defined(TRANSPONDER) // TODO - Add transponder feature if ((WS2811_DMA_TC_FLAG == TRANSPONDER_DMA_TC_FLAG) && featureConfigured(FEATURE_TRANSPONDER) && featureConfigured(FEATURE_LED_STRIP)) { featureClear(FEATURE_LED_STRIP); } #endif */ #if defined(CC3D) && defined(SONAR) && defined(USE_SOFTSERIAL1) && defined(RSSI_ADC_GPIO) // shared pin if ((featureConfigured(FEATURE_SONAR) + featureConfigured(FEATURE_SOFTSERIAL) + featureConfigured(FEATURE_RSSI_ADC)) > 1) { featureClear(FEATURE_SONAR); featureClear(FEATURE_SOFTSERIAL); featureClear(FEATURE_RSSI_ADC); } #endif #if defined(COLIBRI_RACE) masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; if (featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_MSP)) { featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_MSP); featureSet(FEATURE_RX_PPM); } #endif useRxConfig(&masterConfig.rxConfig); serialConfig_t *serialConfig = &masterConfig.serialConfig; if (!isSerialConfigValid(serialConfig)) { resetSerialConfig(serialConfig); } }