void varioWakeup() { if (isFunctionActive(FUNCTION_VARIO)) { int varioFreq, varioDuration, varioPause=0; uint8_t varioFlags; int verticalSpeed = 0; if (g_model.frsky.varioSource) { uint8_t item = g_model.frsky.varioSource-1; if (item < MAX_SENSORS) { verticalSpeed = telemetryItems[item].value * g_model.telemetrySensors[item].getPrecMultiplier(); } } int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50; int varioCenterMax = (int)g_model.frsky.varioCenterMax * 10 + 50; int varioMax = (10+(int)g_model.frsky.varioMax) * 100; int varioMin = (-10+(int)g_model.frsky.varioMin) * 100; if (verticalSpeed > varioMax) verticalSpeed = varioMax; else if (verticalSpeed < varioMin) verticalSpeed = varioMin; if (verticalSpeed <= varioCenterMin) { varioFreq = VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10) - (((VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)-((VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10))/2)) * (verticalSpeed-varioCenterMin)) / varioMin); varioDuration = 80; // continuous beep: we will enter again here before the tone ends varioFlags = PLAY_BACKGROUND|PLAY_NOW; } else if (verticalSpeed >= varioCenterMax || !g_model.frsky.varioCenterSilent) { varioFreq = VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10) + (((VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10)) * (verticalSpeed-varioCenterMin)) / varioMax); int varioPeriod = VARIO_REPEAT_MAX + ((VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10)-VARIO_REPEAT_MAX) * (varioMax-verticalSpeed) * (varioMax-verticalSpeed)) / ((varioMax-varioCenterMin) * (varioMax-varioCenterMin)); if (verticalSpeed >= varioCenterMax || varioCenterMin == varioCenterMax) varioDuration = varioPeriod / 5; else varioDuration = varioPeriod * (85 - (((verticalSpeed-varioCenterMin) * 25) / (varioCenterMax-varioCenterMin))) / 100; varioPause = varioPeriod - varioDuration; varioFlags = PLAY_BACKGROUND; } else { return; } AUDIO_VARIO(varioFreq, varioDuration, varioPause, varioFlags); } }
void writeLogs() { static const pm_char * error_displayed = NULL; if (isFunctionActive(FUNCTION_LOGS) && logDelay > 0) { tmr10ms_t tmr10ms = get_tmr10ms(); if (lastLogTime == 0 || (tmr10ms_t)(tmr10ms - lastLogTime) >= (tmr10ms_t)logDelay*10) { lastLogTime = tmr10ms; if (!g_oLogFile.fs) { const pm_char * result = openLogs(); if (result != NULL) { if (result != error_displayed) { error_displayed = result; POPUP_WARNING(result); } return; } } #if defined(RTCLOCK) { static struct gtm utm; static gtime_t lastRtcTime = 0; if ( g_rtcTime != lastRtcTime ) { lastRtcTime = g_rtcTime; gettime(&utm); } f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d.%02d0,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100); } #else f_printf(&g_oLogFile, "%d,", tmr10ms); #endif #if defined(FRSKY) #if !defined(CPUARM) f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, RAW_FRSKY_MINMAX(frskyData.rssi[0]), RAW_FRSKY_MINMAX(frskyData.rssi[1])); for (uint8_t i=0; i<MAX_FRSKY_A_CHANNELS; i++) { int16_t converted_value = applyChannelRatio(i, RAW_FRSKY_MINMAX(frskyData.analog[i])); f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100); } #if defined(FRSKY_HUB) TELEMETRY_BARO_ALT_PREPARE(); if (IS_USR_PROTO_FRSKY_HUB()) { f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d,%03d.%04d%c,%03d.%04d%c,%03d.%02d," TELEMETRY_GPS_SPEED_FORMAT TELEMETRY_GPS_ALT_FORMAT TELEMETRY_BARO_ALT_FORMAT TELEMETRY_VSPEED_FORMAT TELEMETRY_ASPEED_FORMAT "%d,%d,%d,%d," TELEMETRY_CELLS_FORMAT TELEMETRY_CURRENT_FORMAT "%d," TELEMETRY_VFAS_FORMAT "%d,%d,%d,", frskyData.hub.year+2000, frskyData.hub.month, frskyData.hub.day, frskyData.hub.hour, frskyData.hub.min, frskyData.hub.sec, frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap, frskyData.hub.gpsLongitudeEW ? frskyData.hub.gpsLongitudeEW : '-', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap, frskyData.hub.gpsLatitudeNS ? frskyData.hub.gpsLatitudeNS : '-', frskyData.hub.gpsCourse_bp, frskyData.hub.gpsCourse_ap, TELEMETRY_GPS_SPEED_ARGS TELEMETRY_GPS_ALT_ARGS TELEMETRY_BARO_ALT_ARGS TELEMETRY_VSPEED_ARGS TELEMETRY_ASPEED_ARGS frskyData.hub.temperature1, frskyData.hub.temperature2, frskyData.hub.rpm, frskyData.hub.fuelLevel, TELEMETRY_CELLS_ARGS TELEMETRY_CURRENT_ARGS frskyData.hub.currentConsumption, TELEMETRY_VFAS_ARGS frskyData.hub.accelX, frskyData.hub.accelY, frskyData.hub.accelZ); } #endif #if defined(WS_HOW_HIGH) if (IS_USR_PROTO_WS_HOW_HIGH()) { f_printf(&g_oLogFile, "%d,", TELEMETRY_RELATIVE_BARO_ALT_BP); } #endif #endif #if defined(CPUARM) for (int i=0; i<MAX_SENSORS; i++) { TelemetrySensor & sensor = g_model.telemetrySensors[i]; TelemetryItem & telemetryItem = telemetryItems[i]; if (sensor.logs) { if (sensor.unit == UNIT_GPS) { if (telemetryItem.gps.longitudeEW && telemetryItem.gps.latitudeNS) f_printf(&g_oLogFile, "%03d.%04d%c %03d.%04d%c,", telemetryItem.gps.longitude_bp, telemetryItem.gps.longitude_ap, telemetryItem.gps.longitudeEW, telemetryItem.gps.latitude_bp, telemetryItem.gps.latitude_ap, telemetryItem.gps.latitudeNS); else f_printf(&g_oLogFile, ","); } else if (sensor.unit == UNIT_DATETIME) { if (telemetryItem.datetime.datestate) f_printf(&g_oLogFile, "%4d-%02d-%02d %02d:%02d:%02d,", telemetryItem.datetime.year, telemetryItem.datetime.month, telemetryItem.datetime.day, telemetryItem.datetime.hour, telemetryItem.datetime.min, telemetryItem.datetime.sec); else f_printf(&g_oLogFile, ","); } else if (sensor.prec == 2) { div_t qr = div(telemetryItem.value, 100); if (telemetryItem.value < 0) f_printf(&g_oLogFile, "-"); f_printf(&g_oLogFile, "%d.%02d,", abs(qr.quot), abs(qr.rem)); } else if (sensor.prec == 1) { div_t qr = div(telemetryItem.value, 10); if (telemetryItem.value < 0) f_printf(&g_oLogFile, "-"); f_printf(&g_oLogFile, "%d.%d,", abs(qr.quot), abs(qr.rem)); } else { f_printf(&g_oLogFile, "%d,", telemetryItem.value); } } } #endif #endif for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) { f_printf(&g_oLogFile, "%d,", calibratedStick[i]); } #if defined(PCBTARANIS) int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d\n", get3PosState(SA), get3PosState(SB), get3PosState(SC), get3PosState(SD), get3PosState(SE), get2PosState(SF), get3PosState(SG), get2PosState(SH)); #endif if (result<0 && !error_displayed) { error_displayed = STR_SDCARD_ERROR; POPUP_WARNING(STR_SDCARD_ERROR); closeLogs(); } } } else { error_displayed = NULL; if (g_oLogFile.fs) { closeLogs(); } } }
// TODO test when disk full void writeLogs() { static const pm_char * error_displayed = NULL; if (isFunctionActive(FUNCTION_LOGS) && logDelay > 0) { tmr10ms_t tmr10ms = get_tmr10ms(); if (lastLogTime == 0 || (tmr10ms_t)(tmr10ms - lastLogTime) >= (tmr10ms_t)logDelay*10) { lastLogTime = tmr10ms; if (!g_oLogFile.fs) { const pm_char * result = openLogs(); if (result != NULL) { if (result != error_displayed) { error_displayed = result; POPUP_WARNING(result); } return; } } #if defined(RTCLOCK) struct gtm utm; gettime(&utm); f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d.%02d0,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100); #else f_printf(&g_oLogFile, "%d,", tmr10ms); #endif #if defined(FRSKY) #if defined(PCBTARANIS) && defined(REVPLUS) f_printf(&g_oLogFile, "%d,", RAW_FRSKY_MINMAX(frskyData.rssi[0])); #elif defined(CPUARM) f_printf(&g_oLogFile, "%d,%d,", RAW_FRSKY_MINMAX(frskyData.swr), RAW_FRSKY_MINMAX(frskyData.rssi[0])); #else f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, RAW_FRSKY_MINMAX(frskyData.rssi[0]), RAW_FRSKY_MINMAX(frskyData.rssi[1])); #endif for (uint8_t i=0; i<MAX_FRSKY_A_CHANNELS; i++) { int16_t converted_value = applyChannelRatio(i, RAW_FRSKY_MINMAX(frskyData.analog[i])); f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100); } #endif #if defined(FRSKY_HUB) TELEMETRY_BARO_ALT_PREPARE(); if (IS_USR_PROTO_FRSKY_HUB()) { f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d,%03d.%04d%c,%03d.%04d%c,%03d.%02d," TELEMETRY_GPS_SPEED_FORMAT TELEMETRY_GPS_ALT_FORMAT TELEMETRY_BARO_ALT_FORMAT TELEMETRY_VSPEED_FORMAT TELEMETRY_ASPEED_FORMAT "%d,%d,%d,%d," TELEMETRY_CELLS_FORMAT TELEMETRY_CURRENT_FORMAT "%d," TELEMETRY_VFAS_FORMAT "%d,%d,%d,", frskyData.hub.year+2000, frskyData.hub.month, frskyData.hub.day, frskyData.hub.hour, frskyData.hub.min, frskyData.hub.sec, frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap, frskyData.hub.gpsLongitudeEW ? frskyData.hub.gpsLongitudeEW : '-', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap, frskyData.hub.gpsLatitudeNS ? frskyData.hub.gpsLatitudeNS : '-', frskyData.hub.gpsCourse_bp, frskyData.hub.gpsCourse_ap, TELEMETRY_GPS_SPEED_ARGS TELEMETRY_GPS_ALT_ARGS TELEMETRY_BARO_ALT_ARGS TELEMETRY_VSPEED_ARGS TELEMETRY_ASPEED_ARGS frskyData.hub.temperature1, frskyData.hub.temperature2, frskyData.hub.rpm, frskyData.hub.fuelLevel, TELEMETRY_CELLS_ARGS TELEMETRY_CURRENT_ARGS frskyData.hub.currentConsumption, TELEMETRY_VFAS_ARGS frskyData.hub.accelX, frskyData.hub.accelY, frskyData.hub.accelZ); } #endif #if defined(WS_HOW_HIGH) if (IS_USR_PROTO_WS_HOW_HIGH()) { f_printf(&g_oLogFile, "%d,", TELEMETRY_RELATIVE_BARO_ALT_BP); } #endif for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) { f_printf(&g_oLogFile, "%d,", calibratedStick[i]); } #if defined(PCBTARANIS) int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d\n", get3PosState(SA), get3PosState(SB), get3PosState(SC), get3PosState(SD), get3PosState(SE), get2PosState(SF), get3PosState(SG), get2PosState(SH)); #else int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d\n", get2PosState(THR), get2PosState(RUD), get2PosState(ELE), get3PosState(ID), get2PosState(AIL), get2PosState(GEA), get2PosState(TRN)); #endif if (result<0 && !error_displayed) { error_displayed = STR_SDCARD_ERROR; POPUP_WARNING(STR_SDCARD_ERROR); closeLogs(); } } } else { error_displayed = NULL; if (g_oLogFile.fs) { closeLogs(); } } }
void evalFunctions() #endif { MASK_FUNC_TYPE newActiveFunctions = 0; MASK_CFN_TYPE newActiveSwitches = 0; #if defined(ROTARY_ENCODERS) && defined(GVARS) static rotenc_t rePreviousValues[ROTARY_ENCODERS]; #endif #if defined(OVERRIDE_CHANNEL_FUNCTION) for (uint8_t i=0; i<NUM_CHNOUT; i++) { safetyCh[i] = OVERRIDE_CHANNEL_UNDEFINED; } #endif #if defined(GVARS) for (uint8_t i=0; i<NUM_STICKS; i++) { trimGvar[i] = -1; } #endif for (uint8_t i=0; i<NUM_CFN; i++) { const CustomFunctionData *cfn = &functions[i]; int8_t swtch = CFN_SWITCH(cfn); if (swtch) { MASK_CFN_TYPE switch_mask = ((MASK_CFN_TYPE)1 << i); #if defined(CPUARM) bool active = getSwitch(swtch, IS_PLAY_FUNC(CFN_FUNC(cfn)) ? GETSWITCH_MIDPOS_DELAY : 0); #else bool active = getSwitch(swtch); #endif if (HAS_ENABLE_PARAM(CFN_FUNC(cfn))) { active &= (bool)CFN_ACTIVE(cfn); } if (active || IS_PLAY_BOTH_FUNC(CFN_FUNC(cfn))) { switch (CFN_FUNC(cfn)) { #if defined(OVERRIDE_CHANNEL_FUNCTION) case FUNC_OVERRIDE_CHANNEL: safetyCh[CFN_CH_INDEX(cfn)] = CFN_PARAM(cfn); break; #endif case FUNC_TRAINER: { uint8_t mask = 0x0f; if (CFN_CH_INDEX(cfn) > 0) { mask = (1<<(CFN_CH_INDEX(cfn)-1)); } newActiveFunctions |= mask; break; } case FUNC_INSTANT_TRIM: newActiveFunctions |= (1 << FUNCTION_INSTANT_TRIM); if (!isFunctionActive(FUNCTION_INSTANT_TRIM)) { #if defined(GUI) if (g_menuStack[0] == menuMainView #if defined(FRSKY) || g_menuStack[0] == menuTelemetryFrsky #endif #if defined(PCBTARANIS) || g_menuStack[0] == menuMainViewChannelsMonitor || g_menuStack[0] == menuChannelsView #endif ) #endif { instantTrim(); } } break; case FUNC_RESET: switch (CFN_PARAM(cfn)) { case FUNC_RESET_TIMER1: case FUNC_RESET_TIMER2: #if defined(CPUARM) case FUNC_RESET_TIMER3: #endif timerReset(CFN_PARAM(cfn)); break; case FUNC_RESET_FLIGHT: flightReset(); break; #if defined(FRSKY) case FUNC_RESET_TELEMETRY: telemetryReset(); break; #endif #if ROTARY_ENCODERS > 0 case FUNC_RESET_ROTENC1: #if ROTARY_ENCODERS > 1 case FUNC_RESET_ROTENC2: #endif g_rotenc[CFN_PARAM(cfn)-FUNC_RESET_ROTENC1] = 0; break; #endif } #if defined(CPUARM) if (CFN_PARAM(cfn)>=FUNC_RESET_PARAM_FIRST_TELEM) { TelemetryItem * telemetryItem = & telemetryItems[CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM]; telemetryItem->clear(); } #endif break; #if defined(CPUARM) case FUNC_SET_TIMER: { timerSet(CFN_TIMER_INDEX(cfn), CFN_PARAM(cfn)); break; } #endif #if 0 //defined(DANGEROUS_MODULE_FUNCTIONS) case FUNC_RANGECHECK: case FUNC_BIND: case FUNC_MODULE_OFF: { unsigned int moduleIndex = CFN_PARAM(cfn); if (moduleIndex < NUM_MODULES) { moduleFlag[moduleIndex] = 1 + CFN_FUNC(cfn) - FUNC_RANGECHECK; } break; } #endif #if defined(GVARS) case FUNC_ADJUST_GVAR: if (CFN_GVAR_MODE(cfn) == 0) { SET_GVAR(CFN_GVAR_INDEX(cfn), CFN_PARAM(cfn), mixerCurrentFlightMode); } else if (CFN_GVAR_MODE(cfn) == 2) { SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_PARAM(cfn), mixerCurrentFlightMode), mixerCurrentFlightMode); } else if (CFN_GVAR_MODE(cfn) == 3) { if (!(functionsContext.activeSwitches & switch_mask)) { SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + (CFN_PARAM(cfn) ? +1 : -1), mixerCurrentFlightMode); } } else if (CFN_PARAM(cfn) >= MIXSRC_TrimRud && CFN_PARAM(cfn) <= MIXSRC_TrimAil) { trimGvar[CFN_PARAM(cfn)-MIXSRC_TrimRud] = CFN_GVAR_INDEX(cfn); } #if defined(ROTARY_ENCODERS) else if (CFN_PARAM(cfn) >= MIXSRC_REa && CFN_PARAM(cfn) < MIXSRC_TrimRud) { int8_t scroll = rePreviousValues[CFN_PARAM(cfn)-MIXSRC_REa] - (g_rotenc[CFN_PARAM(cfn)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY); if (scroll) { SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, mixerCurrentFlightMode); } } #endif else { SET_GVAR(CFN_GVAR_INDEX(cfn), calcRESXto100(getValue(CFN_PARAM(cfn))), mixerCurrentFlightMode); } break; #endif #if defined(CPUARM) && defined(SDCARD) case FUNC_VOLUME: { getvalue_t raw = getValue(CFN_PARAM(cfn)); //only set volume if input changed more than hysteresis if (abs(requiredSpeakerVolumeRawLast - raw) > VOLUME_HYSTERESIS) { requiredSpeakerVolumeRawLast = raw; } requiredSpeakerVolume = ((1024 + requiredSpeakerVolumeRawLast) * VOLUME_LEVEL_MAX) / 2048; break; } #endif #if defined(CPUARM) && defined(SDCARD) case FUNC_PLAY_SOUND: case FUNC_PLAY_TRACK: case FUNC_PLAY_VALUE: #if defined(HAPTIC) case FUNC_HAPTIC: #endif { tmr10ms_t tmr10ms = get_tmr10ms(); uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); if (!IS_SILENCE_PERIOD_ELAPSED() && repeatParam == CFN_PLAY_REPEAT_NOSTART) { functionsContext.lastFunctionTime[i] = tmr10ms; } if (!functionsContext.lastFunctionTime[i] || (repeatParam && repeatParam!=CFN_PLAY_REPEAT_NOSTART && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=100*repeatParam)) { if (!IS_PLAYING(i+1)) { functionsContext.lastFunctionTime[i] = tmr10ms; if (CFN_FUNC(cfn) == FUNC_PLAY_SOUND) { AUDIO_PLAY(AU_FRSKY_FIRST+CFN_PARAM(cfn)); } else if (CFN_FUNC(cfn) == FUNC_PLAY_VALUE) { PLAY_VALUE(CFN_PARAM(cfn), i+1); } #if defined(HAPTIC) else if (CFN_FUNC(cfn) == FUNC_HAPTIC) { haptic.event(AU_FRSKY_LAST+CFN_PARAM(cfn)); } #endif else { playCustomFunctionFile(cfn, i+1); } } } break; } case FUNC_BACKGND_MUSIC: newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC); if (!IS_PLAYING(i+1)) { playCustomFunctionFile(cfn, i+1); } break; case FUNC_BACKGND_MUSIC_PAUSE: newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC_PAUSE); break; #elif defined(VOICE) case FUNC_PLAY_SOUND: case FUNC_PLAY_TRACK: case FUNC_PLAY_BOTH: case FUNC_PLAY_VALUE: { tmr10ms_t tmr10ms = get_tmr10ms(); uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); if (!functionsContext.lastFunctionTime[i] || (CFN_FUNC(cfn)==FUNC_PLAY_BOTH && active!=(bool)(functionsContext.activeSwitches&switch_mask)) || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) { functionsContext.lastFunctionTime[i] = tmr10ms; uint8_t param = CFN_PARAM(cfn); if (CFN_FUNC(cfn) == FUNC_PLAY_SOUND) { AUDIO_PLAY(AU_FRSKY_FIRST+param); } else if (CFN_FUNC(cfn) == FUNC_PLAY_VALUE) { PLAY_VALUE(param, i+1); } else { #if defined(GVARS) if (CFN_FUNC(cfn) == FUNC_PLAY_TRACK && param > 250) param = GVAR_VALUE(param-251, getGVarFlightPhase(mixerCurrentFlightMode, param-251)); #endif PUSH_CUSTOM_PROMPT(active ? param : param+1, i+1); } } if (!active) { // PLAY_BOTH would change activeFnSwitches otherwise switch_mask = 0; } break; } #else case FUNC_PLAY_SOUND: { tmr10ms_t tmr10ms = get_tmr10ms(); uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); if (!functionsContext.lastFunctionTime[i] || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) { functionsContext.lastFunctionTime[i] = tmr10ms; AUDIO_PLAY(AU_FRSKY_FIRST+CFN_PARAM(cfn)); } break; } #endif #if defined(FRSKY) && defined(VARIO) case FUNC_VARIO: newActiveFunctions |= (1 << FUNCTION_VARIO); break; #endif #if defined(HAPTIC) && !defined(CPUARM) case FUNC_HAPTIC: { tmr10ms_t tmr10ms = get_tmr10ms(); uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); if (!functionsContext.lastFunctionTime[i] || (repeatParam && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=1000*repeatParam)) { functionsContext.lastFunctionTime[i] = tmr10ms; haptic.event(AU_FRSKY_LAST+CFN_PARAM(cfn)); } break; } #endif #if defined(SDCARD) case FUNC_LOGS: if (CFN_PARAM(cfn)) { newActiveFunctions |= (1 << FUNCTION_LOGS); logDelay = CFN_PARAM(cfn); } break; #endif case FUNC_BACKLIGHT: newActiveFunctions |= (1 << FUNCTION_BACKLIGHT); break; #if defined(PCBTARANIS) case FUNC_SCREENSHOT: if (!(functionsContext.activeSwitches & switch_mask)) { requestScreenshot = true; } break; #endif #if defined(DEBUG) case FUNC_TEST: testFunc(); break; #endif } newActiveSwitches |= switch_mask; } else { functionsContext.lastFunctionTime[i] = 0; } } } functionsContext.activeSwitches = newActiveSwitches; functionsContext.activeFunctions = newActiveFunctions; #if defined(ROTARY_ENCODERS) && defined(GVARS) for (uint8_t i=0; i<ROTARY_ENCODERS; i++) { rePreviousValues[i] = (g_rotenc[i] / ROTARY_ENCODER_GRANULARITY); } #endif }