diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index 07919466c..6a85f8cf9 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -74,7 +74,7 @@ const uint8_t modn12x3[4][4]= { #define C9X_MAX_ENCODERS 2 #define C9X_NUM_CHNOUT 32 // number of real output channels #define C9X_NUM_CSW 32 // number of custom switches -#define C9X_MAX_CUSTOM_FUNCTIONS 32 // number of functions assigned to switches +#define C9X_MAX_CUSTOM_FUNCTIONS 64 // number of functions assigned to switches #define C9X_NUM_MODULES 2 #define STK_RUD 1 @@ -856,7 +856,7 @@ class ModuleData { void clear() { memset(this, 0, sizeof(ModuleData)); } }; -#define C9X_MAX_SCRIPTS 3 +#define C9X_MAX_SCRIPTS 7 #define C9X_MAX_SCRIPT_INPUTS 10 class ScriptData { public: diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 37f148900..ebbc010ec 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -20,7 +20,7 @@ #define MAX_CHANNELS(board, version) (IS_ARM(board) ? 32 : 16) #define MAX_EXPOS(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 64 : 32) : (IS_DBLRAM(board, version) ? 16 : 14)) #define MAX_CUSTOM_SWITCHES(board, version) (IS_ARM(board) ? 32 : (IS_DBLEEPROM(board, version) ? 15 : 12)) -#define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? 32 : (IS_DBLEEPROM(board, version) ? 24 : 16)) +#define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16)) #define MAX_CURVES(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 32 : 16) : O9X_MAX_CURVES) #define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5) @@ -164,7 +164,7 @@ class SourcesConversionTable: public ConversionTable { if (IS_TARANIS(board) && version >= 216) { for (int i=0; i<32; i++) addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i), val++); - for (int i=0; i<3; i++) { + for (int i=0; i<7; i++) { for (int j=0; j<6; j++) { addConversion(RawSource(SOURCE_TYPE_LUA_INPUT, i*16+j), val++); } @@ -1429,7 +1429,9 @@ class ArmCustomFunctionField: public TransformedField { internalField.Append(new SwitchField<8>(fn.swtch, board, version)); internalField.Append(new ConversionField< UnsignedField<8> >((unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function"))); - if (IS_TARANIS(board)) + if (IS_TARANIS(board) && version >= 216) + internalField.Append(new CharField<8>(_param, false)); + else if (IS_TARANIS(board)) internalField.Append(new CharField<10>(_param, false)); else internalField.Append(new CharField<6>(_param, false)); @@ -2208,7 +2210,7 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u } if (IS_TARANIS(board) && version >= 216) { - for (int i=0; i<3; i++) { + for (int i=0; i<7; i++) { ScriptData & script = modelData.scriptData[i]; internalField.Append(new ZCharField<10>(script.filename)); internalField.Append(new ZCharField<10>(script.name)); diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 0b832e086..2f4b0409b 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -517,7 +517,7 @@ int OpenTxInterface::getCapability(const Capability capability) return (IS_TARANIS(board) ? 22 : 9); case CustomFunctions: if (IS_ARM(board)) - return 32; + return 64; else if (board==BOARD_GRUVIN9X||board==BOARD_M128) return 24; else @@ -550,7 +550,7 @@ int OpenTxInterface::getCapability(const Capability capability) case VoicesAsNumbers: return (IS_ARM(board) ? 0 : 1); case VoicesMaxLength: - return (IS_ARM(board) ? (IS_TARANIS(board) ? 10 : 6) : 0); + return (IS_ARM(board) ? (IS_TARANIS(board) ? 8 : 6) : 0); case MultiLangVoice: return (IS_ARM(board) ? 1 : 0); case SoundPitch: diff --git a/radio/src/audio_arm.cpp b/radio/src/audio_arm.cpp index 5d2fb1be9..8e9f4a741 100644 --- a/radio/src/audio_arm.cpp +++ b/radio/src/audio_arm.cpp @@ -117,132 +117,260 @@ const char * audioFilenames[] = { }; uint64_t sdAvailableSystemAudioFiles = 0; -uint8_t sdAvailablePhaseAudioFiles[MAX_PHASES] = { 0 }; -uint8_t sdAvailableMixerAudioFiles[MAX_MIXERS] = { 0 }; +uint32_t sdAvailablePhaseAudioFiles = 0; +uint64_t sdAvailableSwitchAudioFiles = 0; +uint64_t sdAvailableLogicalSwitchAudioFiles = 0; -void refreshSystemAudioFiles() +#define MASK_SYSTEM_AUDIO_FILE(index) ((uint64_t)1 << index) +#define MASK_PHASE_AUDIO_FILE(index, event) ((uint32_t)1 << (2*index+event)) +#define MASK_SWITCH_AUDIO_FILE(index) ((uint64_t)1 << index) +#define MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event) ((uint64_t)1 << (2*index+event)) + +bool isFileAvailable(const char * filename) { FILINFO info; -#if _USE_LFN TCHAR lfn[_MAX_LFN + 1]; info.lfname = lfn; info.lfsize = sizeof(lfn); -#endif + return f_stat(filename, &info) == FR_OK; +} - char filename[32] = SYSTEM_SOUNDS_PATH "/"; - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); +char * getAudioPath(char * path) +{ + strcpy(path, SOUNDS_PATH "/"); + strncpy(path+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); + return path + sizeof(SOUNDS_PATH); +} + +char * getSystemAudioPath(char * path) +{ + char * str = getAudioPath(path); + strcpy(str, SYSTEM_SUBDIR "/"); + return str + sizeof(SYSTEM_SUBDIR); +} + +void getSystemAudioFile(char * filename, int index) +{ + char * str = getSystemAudioPath(filename); + strcpy(str, audioFilenames[index]); + strcat(str, SOUNDS_EXT); +} + +void referenceSystemAudioFiles() +{ + char path[AUDIO_FILENAME_MAXLEN+1]; + FILINFO fno; + DIR dir; + char *fn; /* This function is assuming non-Unicode cfg. */ + TCHAR lfn[_MAX_LFN + 1]; + fno.lfname = lfn; + fno.lfsize = sizeof(lfn); + + uint64_t availableAudioFiles = 0; assert(sizeof(audioFilenames)==AU_FRSKY_FIRST*sizeof(char *)); assert(sizeof(sdAvailableSystemAudioFiles)*8 >= AU_FRSKY_FIRST); - uint64_t availableAudioFiles = 0; + char * filename = getSystemAudioPath(path); + *(filename-1) = '\0'; - for (uint32_t i=0; iid, 2); + char * result = strcat_modelname(path+sizeof(SOUNDS_PATH), g_eeGeneral.currModel); + *result++ = '/'; + *result = '\0'; return result; } -void refreshModelAudioFiles() +void getPhaseAudioFile(char * filename, int index, unsigned int event) { - FILINFO info; + char * str = getModelPath(filename); + char * tmp = strcat_phasename(str, index); + strcpy(tmp, suffixes[event]); + strcat(tmp, SOUNDS_EXT); +} + +void getSwitchAudioFile(char * filename, int index) +{ + char * str = getModelPath(filename); + int len = STR_VSWITCHES[0]; + strncpy(str, &STR_VSWITCHES[1+len*index], len); + str += len-1; + if (*str == '\300') { + strcpy(str, "-up"); + str += 3; + } + else if (*str == '-') { + strcpy(str, "-mid"); + str += 4; + } + else if (*str == '\301') { + strcpy(str, "-down"); + str += 5; + } + else { + str += 1; + } + strcat(str, SOUNDS_EXT); +} + +void getLogicalSwitchAudioFile(char * filename, int index, unsigned int event) +{ + char * str = getModelPath(filename); + int len = STR_VSWITCHES[0]; + strncpy(str, &STR_VSWITCHES[1+len*(index+SWSRC_FIRST_CSW-1)], len); + str += len; + strcpy(str, suffixes[event]); + strcat(str, SOUNDS_EXT); +} + +void referenceModelAudioFiles() +{ + char path[AUDIO_FILENAME_MAXLEN+1]; + FILINFO fno; + DIR dir; + char *fn; /* This function is assuming non-Unicode cfg. */ TCHAR lfn[_MAX_LFN + 1]; - info.lfname = lfn; - info.lfsize = sizeof(lfn); + fno.lfname = lfn; + fno.lfsize = sizeof(lfn); - char filename[AUDIO_FILENAME_MAXLEN+1] = SOUNDS_PATH "/"; - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - - if (sdMounted()) { - char *buf = strcat_modelname(&filename[sizeof(SOUNDS_PATH)], g_eeGeneral.currModel); - *buf++ = '/'; + sdAvailablePhaseAudioFiles = 0; + sdAvailableSwitchAudioFiles = 0; + sdAvailableLogicalSwitchAudioFiles = 0; - for (uint32_t i=0; i-[on|off].wav + for (int i=0; i-[up|mid|down].wav + for (int i=0; i-[on|off].wav + for (int i=0; i> 24); uint8_t index = (i >> 16) & 0xFF; uint8_t event = i & 0xFF; #if 0 - printf("isAudioFileAvailable(%08x)\n", i); fflush(stdout); + printf("isAudioFileReferenced(%08x)\n", i); fflush(stdout); #endif if (category == SYSTEM_AUDIO_CATEGORY) { - if (sdAvailableSystemAudioFiles & ((uint64_t)1 << event)) { - strcpy(filename, SYSTEM_SOUNDS_PATH "/"); - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - strcpy(filename+sizeof(SYSTEM_SOUNDS_PATH), audioFilenames[i]); - strcat(filename+sizeof(SYSTEM_SOUNDS_PATH), SOUNDS_EXT); + if (sdAvailableSystemAudioFiles & MASK_SYSTEM_AUDIO_FILE(event)) { + getSystemAudioFile(filename, event); return true; } } else if (category == PHASE_AUDIO_CATEGORY) { - if (sdAvailablePhaseAudioFiles[index] & ((uint32_t)1 << event)) { - strcpy(filename, SOUNDS_PATH "/"); - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel); - *str++ = '/'; - char * tmp = strcat_phasename(str, index); - if (tmp != str) { - strcpy(tmp, suffixes[event]); - strcat(tmp, SOUNDS_EXT); - return true; - } + if (sdAvailablePhaseAudioFiles & MASK_PHASE_AUDIO_FILE(index, event)) { + getPhaseAudioFile(filename, index, event); + return true; } } - else if (category == MIXER_AUDIO_CATEGORY) { - if (sdAvailableMixerAudioFiles[index] & ((uint32_t)1 << event)) { - strcpy(filename, SOUNDS_PATH "/"); - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel); - *str++ = '/'; - char * tmp = strcat_mixername(str, index); - if (tmp != str) { - strcpy(tmp, suffixes[event]); - strcat(tmp, SOUNDS_EXT); - return true; - } + else if (category == SWITCH_AUDIO_CATEGORY) { + if (sdAvailableSwitchAudioFiles & MASK_SWITCH_AUDIO_FILE(index)) { + getSwitchAudioFile(filename, index); + return true; + } + } + else if (category == LOGICAL_SWITCH_AUDIO_CATEGORY) { + if (sdAvailableLogicalSwitchAudioFiles & MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event)) { + getLogicalSwitchAudioFile(filename, index, event); + return true; } } return false; } + +tmr10ms_t timeAutomaticPromptsSilence = 0; + +void playModelEvent(uint8_t category, uint8_t index, uint8_t event) +{ + char filename[AUDIO_FILENAME_MAXLEN+1]; + if ((get_tmr10ms()-timeAutomaticPromptsSilence > 50) && isAudioFileReferenced((category << 24) + (index << 16) + event, filename)) { + audioQueue.playFile(filename); + } +} #else -#define isAudioFileAvailable(i, f) false + +#define isAudioFileReferenced(i, f) false + #endif +// TODO should be generated and in flash rather than in ram int16_t alawTable[256]; int16_t ulawTable[256]; @@ -757,10 +885,6 @@ void AudioQueue::reset() void audioEvent(uint8_t e, uint16_t f) { -#if defined(SDCARD) - char filename[AUDIO_FILENAME_MAXLEN+1]; -#endif - #if defined(HAPTIC) haptic.event(e); //do this before audio to help sync timings #endif @@ -773,7 +897,8 @@ void audioEvent(uint8_t e, uint16_t f) if (g_eeGeneral.beepMode>0 || (g_eeGeneral.beepMode==0 && e>=AU_TRIM_MOVE) || (g_eeGeneral.beepMode>=-1 && e<=AU_ERROR)) { #if defined(SDCARD) - if (e < AU_FRSKY_FIRST && isAudioFileAvailable(e, filename)) { + char filename[AUDIO_FILENAME_MAXLEN+1]; + if (e < AU_FRSKY_FIRST && isAudioFileReferenced(e, filename)) { audioQueue.playFile(filename); } else @@ -982,16 +1107,13 @@ void audioEvent(uint8_t e, uint16_t f) void pushPrompt(uint16_t prompt, uint8_t id) { #if defined(SDCARD) - - char filename[] = SYSTEM_SOUNDS_PATH "/0000" SOUNDS_EXT; - strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - + char filename[AUDIO_FILENAME_MAXLEN+1]; + char * str = getSystemAudioPath(filename); + strcpy(str, "0000" SOUNDS_EXT); for (int8_t i=3; i>=0; i--) { - filename[sizeof(SYSTEM_SOUNDS_PATH)+i] = '0' + (prompt%10); + str[i] = '0' + (prompt%10); prompt /= 10; } - audioQueue.playFile(filename, 0, id); - #endif } diff --git a/radio/src/audio_arm.h b/radio/src/audio_arm.h index 9b45187b0..3f5ee974c 100644 --- a/radio/src/audio_arm.h +++ b/radio/src/audio_arm.h @@ -277,16 +277,21 @@ void audioStart(); #define AUDIO_HEARTBEAT() -#define SYSTEM_AUDIO_CATEGORY 0 -#define MODEL_AUDIO_CATEGORY 1 -#define PHASE_AUDIO_CATEGORY 2 -#define MIXER_AUDIO_CATEGORY 3 +enum AutomaticPromptsCategories { + SYSTEM_AUDIO_CATEGORY, + MODEL_AUDIO_CATEGORY, + PHASE_AUDIO_CATEGORY, + SWITCH_AUDIO_CATEGORY, + LOGICAL_SWITCH_AUDIO_CATEGORY, +}; -#define AUDIO_EVENT_OFF 0 -#define AUDIO_EVENT_ON 1 -#define AUDIO_EVENT_BG 2 +enum AutomaticPromptsEvents { + AUDIO_EVENT_OFF, + AUDIO_EVENT_ON, + AUDIO_EVENT_MID, +}; -extern void pushPrompt(uint16_t prompt, uint8_t id=0); +void pushPrompt(uint16_t prompt, uint8_t id=0); #define I18N_PLAY_FUNCTION(lng, x, ...) void lng ## _ ## x(__VA_ARGS__, uint8_t id) #define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__, uint8_t id) @@ -300,15 +305,26 @@ extern void pushPrompt(uint16_t prompt, uint8_t id=0); #define AUDIO_RESET() audioQueue.reset() #if defined(SDCARD) - #define PLAY_PHASE_OFF(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileAvailable((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_OFF, filename)) audioQueue.playFile(filename); } while (0) - #define PLAY_PHASE_ON(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileAvailable((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_ON, filename)) audioQueue.playFile(filename); } while (0) + extern tmr10ms_t timeAutomaticPromptsSilence; + void playModelEvent(uint8_t category, uint8_t index, uint8_t event=0); + #define PLAY_PHASE_OFF(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_OFF) + #define PLAY_PHASE_ON(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_ON) + #define PLAY_SWITCH_MOVED(sw) playModelEvent(SWITCH_AUDIO_CATEGORY, sw) + #define PLAY_LOGICAL_SWITCH_OFF(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_OFF) + #define PLAY_LOGICAL_SWITCH_ON(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_ON) + #define SKIP_AUTOMATIC_PROMPTS() timeAutomaticPromptsSilence = get_tmr10ms() #else #define PLAY_PHASE_OFF(phase) #define PLAY_PHASE_ON(phase) + #define PLAY_SWITCH_MOVED(sw) + #define PLAY_LOGICAL_SWITCH_OFF(sw) + #define PLAY_LOGICAL_SWITCH_ON(sw) + #define SKIP_AUTOMATIC_PROMPTS() #endif -extern void refreshSystemAudioFiles(); -extern void refreshModelAudioFiles(); -extern bool isAudioFileAvailable(uint32_t i, char * filename); +void referenceSystemAudioFiles(); +void referenceModelAudioFiles(); + +bool isAudioFileReferenced(uint32_t i, char * filename/*at least AUDIO_FILENAME_MAXLEN+1 long*/); #endif diff --git a/radio/src/audio_avr.h b/radio/src/audio_avr.h index 6302c13f4..691305655 100644 --- a/radio/src/audio_avr.h +++ b/radio/src/audio_avr.h @@ -157,5 +157,9 @@ void audioDefevent(uint8_t e); #define PLAY_PHASE_OFF(phase) #define PLAY_PHASE_ON(phase) +#define PLAY_SWITCH_MOVED(sw) +#define PLAY_LOGICAL_SWITCH_OFF(sw) +#define PLAY_LOGICAL_SWITCH_ON(sw) +#define SKIP_AUTOMATIC_PROMPTS() #endif diff --git a/radio/src/buzzer.h b/radio/src/buzzer.h index cbb4d5717..6d901bbbb 100644 --- a/radio/src/buzzer.h +++ b/radio/src/buzzer.h @@ -102,6 +102,10 @@ void beep(uint8_t val); #define PLAY_PHASE_OFF(phase) #define PLAY_PHASE_ON(phase) + #define PLAY_SWITCH_MOVED(sw) + #define PLAY_LOGICAL_SWITCH_OFF(sw) + #define PLAY_LOGICAL_SWITCH_ON(sw) + #define SKIP_AUTOMATIC_PROMPTS() #endif #if !defined(CPUARM) diff --git a/radio/src/eeprom_conversions.cpp b/radio/src/eeprom_conversions.cpp index f12353cb0..e575f4c1c 100644 --- a/radio/src/eeprom_conversions.cpp +++ b/radio/src/eeprom_conversions.cpp @@ -144,7 +144,7 @@ PACK(typedef struct { int8_t swtch; uint8_t func; PACK(union { - char name[LEN_CFN_NAME]; + char name[10]; struct { int16_t val; int16_t ext1; @@ -193,7 +193,7 @@ PACK(typedef struct { int8_t points[NUM_POINTS]; LogicalSwitchData_v215 customSw[NUM_CSW]; - CustomFnData_v215 funcSw[NUM_CFN]; + CustomFnData_v215 funcSw[32]; SwashRingData swashR; PhaseData_v215 phaseData[MAX_PHASES]; @@ -593,7 +593,7 @@ void ConvertModel_215_to_216(ModelData &model) } if (fn.func == FUNC_PLAY_TRACK || fn.func == FUNC_BACKGND_MUSIC) { - memcpy(fn.play.name, oldModel.funcSw[i].param.name, LEN_CFN_NAME); + memcpy(fn.play.name, oldModel.funcSw[i].param.name, 8); } else { fn.all.val = oldModel.funcSw[i].param.composite.val; diff --git a/radio/src/eeprom_raw.cpp b/radio/src/eeprom_raw.cpp index 718fe3558..5050f7cbb 100644 --- a/radio/src/eeprom_raw.cpp +++ b/radio/src/eeprom_raw.cpp @@ -404,7 +404,7 @@ void eeLoadModel(uint8_t id) #endif #if defined(CPUARM) && defined(SDCARD) - refreshModelAudioFiles(); + referenceModelAudioFiles(); #endif LOAD_MODEL_BITMAP(); diff --git a/radio/src/eeprom_rlc.cpp b/radio/src/eeprom_rlc.cpp index f6f62502e..190dcdbe8 100644 --- a/radio/src/eeprom_rlc.cpp +++ b/radio/src/eeprom_rlc.cpp @@ -978,7 +978,7 @@ void eeLoadModel(uint8_t id) #endif #if defined(CPUARM) && defined(SDCARD) - refreshModelAudioFiles(); + referenceModelAudioFiles(); #endif LOAD_MODEL_BITMAP(); diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index d1dd68a46..babd953cb 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -5139,8 +5139,8 @@ void onModelCustomScriptMenu(const char *result) ScriptData &sd = g_model.scriptsData[s_currIdx]; if (result == STR_UPDATE_LIST) { - if (!listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), NULL)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + if (!listSdFiles(SCRIPTS_PATH, SCRIPTS_EXT, sizeof(sd.file), NULL)) { + POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); s_menu_flags = 0; } } @@ -5187,7 +5187,7 @@ void menuModelCustomScriptOne(uint8_t event) lcd_putsiAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && !READ_ONLY()) { s_editMode = 0; - if (listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { + if (listSdFiles(SCRIPTS_PATH, SCRIPTS_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { menuHandler = onModelCustomScriptMenu; } else { diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index 0e18824fa..1a2ab9e1a 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -935,10 +935,10 @@ void luaLoadModelScript(uint8_t index) sid.state = SCRIPT_NOFILE; if (ZEXIST(sd.file)) { - char filename[sizeof(SCRIPTS_PATH)+sizeof(sd.file)+sizeof(MIXES_EXT)] = SCRIPTS_PATH "/"; + char filename[sizeof(SCRIPTS_PATH)+sizeof(sd.file)+sizeof(SCRIPTS_EXT)] = SCRIPTS_PATH "/"; strncpy(filename+sizeof(SCRIPTS_PATH), sd.file, sizeof(sd.file)); filename[sizeof(SCRIPTS_PATH)+sizeof(sd.file)] = '\0'; - strcat(filename+sizeof(SCRIPTS_PATH), MIXES_EXT); + strcat(filename+sizeof(SCRIPTS_PATH), SCRIPTS_EXT); luaLoad(filename, sid); } } diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 94b6cbb9e..39608c17b 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -74,8 +74,8 @@ #define MAX_MIXERS 64 #define MAX_EXPOS 64 #define NUM_CSW 32 // number of custom switches - #define NUM_CFN 32 // number of functions assigned to switches - #define MAX_SCRIPTS 3 + #define NUM_CFN 64 // number of functions assigned to switches + #define MAX_SCRIPTS 7 #define MAX_INPUTS 32 #elif defined(CPUARM) #define MAX_MODELS 60 @@ -84,7 +84,7 @@ #define MAX_MIXERS 64 #define MAX_EXPOS 32 #define NUM_CSW 32 // number of custom switches - #define NUM_CFN 32 // number of functions assigned to switches + #define NUM_CFN 64 // number of functions assigned to switches #elif defined(CPUM2560) || defined(CPUM2561) #define MAX_MODELS 30 #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 @@ -323,8 +323,9 @@ enum BacklightMode { #define SPLASH_MODE uint8_t splashMode:1; uint8_t spare4:2 #endif -#if defined(PCBTARANIS) #define POTS_POS_COUNT 6 + +#if defined(PCBTARANIS) PACK(typedef struct { uint8_t count; uint8_t steps[POTS_POS_COUNT-1]; @@ -822,7 +823,7 @@ enum AdjustGvarFunctionParam { #if defined(CPUARM) #if defined(PCBTARANIS) - #define LEN_CFN_NAME 10 + #define LEN_CFN_NAME 8 #else #define LEN_CFN_NAME 6 #endif diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 36d95d213..cbca81765 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1314,7 +1314,6 @@ getvalue_t getValue(uint8_t i) volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used = 0; volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value = 0; -/* recursive function. stack as of today (16/03/2012) grows by 8bytes at each call, which is ok! */ #if defined(CPUARM) uint32_t cswDelays[NUM_CSW]; @@ -1327,27 +1326,66 @@ tmr10ms_t switchesMidposStart[6] = { 0 }; uint32_t switchesPos = 0; tmr10ms_t potsLastposStart[NUM_XPOTS]; uint8_t potsPos[NUM_XPOTS]; + +uint32_t check2PosSwitchPosition(EnumKeys sw) +{ + uint32_t result; + uint32_t index; + + if (switchState(sw)) + index = sw - SW_SA0; + else + index = sw - SW_SA0 + 1; + + result = (1 << index); + + if (!(switchesPos & result)) { + PLAY_SWITCH_MOVED(index); + } + + return result; +} + #define DELAY_SWITCH_3POS 10/*100ms*/ -#define CHECK_2POS(sw) newPos |= (switchState(sw ## 0) ? (1 << (sw ## 0 - SW_SA0)) : (1 << (sw ## 0 - SW_SA0 + 1))) -#define CHECK_3POS(idx, sw) if (switchState(sw ## 0)) { \ - newPos |= (1 << (sw ## 0 - SW_SA0)); \ - switchesMidposStart[idx] = 0; \ - } \ - else if (switchState(sw ## 2)) { \ - newPos |= (1 << (sw ## 0 - SW_SA0 + 2)); \ - switchesMidposStart[idx] = 0; \ - } \ - else if ((switchesPos & (1 << (sw ## 0 - SW_SA0 + 1))) || (switchesMidposStart[idx] && (tmr10ms_t)(get_tmr10ms() - switchesMidposStart[idx]) > DELAY_SWITCH_3POS)) { \ - newPos |= (1 << (sw ## 0 - SW_SA0 + 1)); \ - switchesMidposStart[idx] = 0; \ - } \ - else { \ - if (!switchesMidposStart[idx]) { \ - switchesMidposStart[idx] = get_tmr10ms(); \ - } \ - newPos |= (switchesPos & (0x7 << (sw ## 0 - SW_SA0))); \ - } -void getSwitchesPosition() +uint32_t check3PosSwitchPosition(uint8_t idx, EnumKeys sw, bool startup) +{ + uint32_t result; + uint32_t index; + + if (switchState(sw)) { + index = sw - SW_SA0; + result = (1 << index); + switchesMidposStart[idx] = 0; + } + else if (switchState(EnumKeys(sw+2))) { + index = sw - SW_SA0 + 2; + result = (1 << index); + switchesMidposStart[idx] = 0; + } + else if (startup || (switchesPos & (1 << (sw - SW_SA0 + 1))) || (switchesMidposStart[idx] && (tmr10ms_t)(get_tmr10ms() - switchesMidposStart[idx]) > DELAY_SWITCH_3POS)) { + index = sw - SW_SA0 + 1; + result = (1 << index); + switchesMidposStart[idx] = 0; + } + else { + index = sw - SW_SA0 + 1; + if (!switchesMidposStart[idx]) { + switchesMidposStart[idx] = get_tmr10ms(); + } + result = (switchesPos & (0x7 << (sw - SW_SA0))); + } + + if (!(switchesPos & result)) { + PLAY_SWITCH_MOVED(index); + } + + return result; +} + +#define CHECK_2POS(sw) newPos |= check2PosSwitchPosition(sw ## 0) +#define CHECK_3POS(idx, sw) newPos |= check3PosSwitchPosition(idx, sw ## 0, startup) + +void getSwitchesPosition(bool startup) { uint32_t newPos = 0; CHECK_3POS(0, SW_SA); @@ -1366,13 +1404,17 @@ void getSwitchesPosition() if (calib->count>0 && calib->countcount); uint8_t previousPos = potsPos[i] >> 4; + uint8_t previousStoredPos = potsPos[i] & 0x0F; if (pos != previousPos) { potsLastposStart[i] = get_tmr10ms(); - potsPos[i] = (pos << 4) | (potsPos[i] & 0x0f); + potsPos[i] = (pos << 4) | previousStoredPos; } - else if ((tmr10ms_t)(get_tmr10ms() - potsLastposStart[i]) > DELAY_SWITCH_3POS) { + else if (startup || (tmr10ms_t)(get_tmr10ms() - potsLastposStart[i]) > DELAY_SWITCH_3POS) { potsLastposStart[i] = 0; - potsPos[i] = (pos << 4) | (pos); + potsPos[i] = (pos << 4) | pos; + if (previousStoredPos != pos) { + PLAY_SWITCH_MOVED(SWSRC_LAST_SWITCH+i*POTS_POS_COUNT+pos); + } } } } @@ -1381,16 +1423,14 @@ void getSwitchesPosition() #define SWITCH_POSITION(sw) (switchesPos & (1<<(sw))) #define POT_POSITION(sw) ((potsPos[(sw)/POTS_POS_COUNT] & 0x0f) == ((sw) % POTS_POS_COUNT)) #else -#define getSwitchesPosition() +#define getSwitchesPosition(...) #define SWITCH_POSITION(idx) switchState((EnumKeys)(SW_BASE+(idx))) #endif int16_t csLastValue[NUM_CSW]; #define CS_LAST_VALUE_INIT -32768 -// param swtch may be (negativ sign ignored) -// 0 --> no source -// 1 .. 9 (or max switches) --> returns switch value including 3pos -// others internal switches etc. + +/* recursive function. stack as of today (16/03/2012) grows by 8bytes at each call, which is ok! */ bool getSwitch(int8_t swtch) { bool result; @@ -1610,10 +1650,14 @@ bool getSwitch(int8_t swtch) } #endif - if (result) + if (result) { + if (!(s_last_switch_value&mask)) PLAY_LOGICAL_SWITCH_ON(cs_idx); s_last_switch_value |= mask; - else + } + else { + if (s_last_switch_value&mask) PLAY_LOGICAL_SWITCH_OFF(cs_idx); s_last_switch_value &= ~mask; + } } } @@ -1644,53 +1688,24 @@ int8_t getMovedSwitch() } } #else - // saves about 50 bytes flash // return delivers 1 to 3 for ID1 to ID3 // 4..8 for all other switches if changed to true // -4..-8 for all other switches if changed to false // 9 for Trainer switch if changed to true; Change to false is ignored - - swstate_t mask=0x80; + swstate_t mask = 0x80; for (uint8_t i=NUM_PSWITCH; i>1; i--) { bool prev; - // mask= (1<<(i-2)); - prev=(switches_states & mask); + prev = (switches_states & mask); // don't use getSwitch here to always get the proper value, even getSwitch manipulates - // bool next = getSwitch(i); - bool next = switchState((EnumKeys)(SW_BASE+i-1)); - if (prev!=next) { - if (((i3)) || next==true) - result = next ? i : -i; - if ((i<=3) && (result==0)) result=1; - switches_states ^= mask; - } - mask>>=1; - } //endfor - -/* - for (uint8_t i=NUM_PSWITCH; i>0; i--) { - bool prev; - swstate_t mask = 0; - if (i <= 3) { - prev = ((switches_states & 0x03) == (i-1)); - } - else { - mask = (1<<(i-2)); - prev = (switches_states & mask); - } - // don't use getSwitch here to always get the proper value, because getSwitch manipulates - // bool next = getSwitch(i); bool next = switchState((EnumKeys)(SW_BASE+i-1)); if (prev != next) { - if (i!=NUM_PSWITCH || next==true) + if (((i3)) || next==true) result = next ? i : -i; - if (mask) - switches_states ^= mask; - else { - switches_states = (switches_states & 0xFC) | (i-1); - } + if (i<=3 && result==0) result = 1; + switches_states ^= mask; } - } //endfor */ + mask >>= 1; + } #endif if ((tmr10ms_t)(get_tmr10ms() - s_move_last_time) > 10) @@ -2303,6 +2318,8 @@ void checkAll() #endif clearKeyEvents(); + + SKIP_AUTOMATIC_PROMPTS(); } #if defined(MODULE_ALWAYS_SEND_PULSES) @@ -2351,30 +2368,39 @@ void checkTHR() if (g_model.disableThrottleWarning) return; getADC(); evalInputs(e_perout_mode_notrainer); // let do evalInputs do the job + int16_t v = calibratedStick[thrchn]; if (v<=(THRCHK_DEADBAND-1024)) return; // prevent warning if throttle input OK + // first - display warning; also deletes inputs if any have been before MESSAGE(STR_THROTTLEWARN, STR_THROTTLENOTIDLE, STR_PRESSANYKEYTOSKIP, AU_THROTTLE_ALERT); - while (1) { - SIMU_SLEEP(1); - getADC(); + while (1) { + + SIMU_SLEEP(1); - evalInputs(e_perout_mode_notrainer); // let do evalInputs do the job - v = calibratedStick[thrchn]; - if (pwrCheck()==e_power_off || keyDown() || v<=(THRCHK_DEADBAND-1024)) - break; + getADC(); + + evalInputs(e_perout_mode_notrainer); // let do evalInputs do the job + v = calibratedStick[thrchn]; + + if (pwrCheck()==e_power_off || keyDown() || v<=(THRCHK_DEADBAND-1024)) + break; - checkBacklight(); - wdt_reset(); - }//endwhile + checkBacklight(); + + wdt_reset(); + } #endif } void checkAlarm() // added by Gohst { - if (g_eeGeneral.disableAlarmWarning) return; - if (IS_SOUND_OFF()) ALERT(STR_ALARMSWARN, STR_ALARMSDISABLED, AU_ERROR); + if (g_eeGeneral.disableAlarmWarning) + return; + + if (IS_SOUND_OFF()) + ALERT(STR_ALARMSWARN, STR_ALARMSDISABLED, AU_ERROR); } void checkSwitches() @@ -2405,19 +2431,21 @@ void checkSwitches() for (uint8_t i=0; i> 6; - if(potMode) { + if (potMode) { perOut(e_perout_mode_normal, 0); bad_pots = 0; - for (uint8_t i=0; i> 3)) > 2)) { - warn = true; - bad_pots |= (1<> 3)) > 2)) { + warn = true; + bad_pots |= (1<> (i*2)]; @@ -2455,7 +2483,7 @@ void checkSwitches() lcd_putcAtt(60+i*(2*FW+FW/2)+FW, 4*FH+3, c, attr); } } - if(potMode) { + if (potMode) { for (uint8_t i=0; i (getValue(MIXSRC_FIRST_POT+i) >> 3) ? 126 : 127); break; - case 2: - case 3: + case 2: + case 3: lcd_putc(60+i*(5*FW)+2*FW+2, 6*FH-2, g_model.potPosition[i] > (getValue(MIXSRC_FIRST_POT+i) >> 3) ? '\300' : '\301'); break; } @@ -2484,11 +2512,11 @@ void checkSwitches() for (uint8_t i=0; i0?(i+3):(states&0x3)+1), attr); + attr = (states & (1 << (i+1))) == (switches_states & (1 << (i+1))) ? 0 : INVERS; + if (!(g_model.nSwToWarn & (1<0?(i+3):(states&0x3)+1), attr); x += 3*FW+FW/2; } #endif @@ -2947,11 +2975,14 @@ void resetAll() #if defined(FRSKY) resetTelemetry(); #endif - for (uint8_t i=0; iHIGH signals start of mixer interrupt #endif - static tmr10ms_t lastTMR; + static tmr10ms_t lastTMR = 0; tmr10ms_t tmr10ms = get_tmr10ms(); - uint8_t tick10ms = (tmr10ms >= lastTMR ? tmr10ms - lastTMR : 1); // handle tick10ms overrun - //@@@ open.20.fsguruh: correct overflow handling costs a lot of code; happens only each 11 min; + uint8_t tick10ms = (tmr10ms >= lastTMR ? tmr10ms - lastTMR : 1); + // handle tick10ms overrun + // correct overflow handling costs a lot of code; happens only each 11 min; // therefore forget the exact calculation and use only 1 instead; good compromise + +#if !defined(CPUARM) lastTMR = tmr10ms; +#endif getADC(); - getSwitchesPosition(); + getSwitchesPosition(lastTMR == 0); + +#if defined(CPUARM) + lastTMR = tmr10ms; +#endif #if defined(PCBSKY9X) && !defined(REVA) && !defined(SIMU) Current_analogue = (Current_analogue*31 + s_anaFilt[8] ) >> 5 ; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 87bbf18e9..786d0d069 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1639,8 +1639,7 @@ uint8_t zlen(const char *str, uint8_t size); bool zexist(const char *str, uint8_t size); char * strcat_zchar(char * dest, char * name, uint8_t size, const char *defaultName, uint8_t defaultNameSize, uint8_t defaultIdx); #define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, STR_MODEL, PSIZE(TR_MODEL), idx+1) -#define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.phaseData[idx].name, LEN_FP_NAME, NULL, 0, 0) -#define strcat_mixername(dest, idx) strcat_zchar(dest, g_model.mixData[idx].name, LEN_EXPOMIX_NAME, NULL, 0, 0) +#define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.phaseData[idx].name, LEN_FP_NAME, STR_FP, PSIZE(TR_FP), idx+1) #define ZLEN(s) zlen(s, sizeof(s)) #define ZEXIST(s) zexist(s, sizeof(s)) #endif diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index 4e6c446d7..ccbad5fa6 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -44,7 +44,7 @@ #define LOGS_PATH ROOT_PATH "LOGS" // no trailing slash = important #define SOUNDS_PATH ROOT_PATH "SOUNDS/en" // no trailing slash = important #define SOUNDS_PATH_LNG_OFS (sizeof(SOUNDS_PATH)-3) -#define SYSTEM_SOUNDS_PATH SOUNDS_PATH "/SYSTEM" // no trailing slash = important +#define SYSTEM_SUBDIR "SYSTEM" // no trailing slash = important #define BITMAPS_PATH ROOT_PATH "BMP" #define SCRIPTS_PATH ROOT_PATH "SCRIPTS" @@ -53,7 +53,6 @@ #define SOUNDS_EXT ".wav" #define BITMAPS_EXT ".bmp" #define SCRIPTS_EXT ".lua" -#define MIXES_EXT ".mix" #define TEXT_EXT ".txt" extern FATFS g_FATFS_Obj; diff --git a/radio/src/simpgmspace.cpp b/radio/src/simpgmspace.cpp index ba52639a3..b00c96be7 100644 --- a/radio/src/simpgmspace.cpp +++ b/radio/src/simpgmspace.cpp @@ -300,7 +300,7 @@ void *main_thread(void *) eeReadAll(); // load general setup and selected model #if defined(CPUARM) && defined(SDCARD) - refreshSystemAudioFiles(); + referenceSystemAudioFiles(); #endif if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on @@ -473,9 +473,10 @@ char *convertSimuPath(const char *path) FRESULT f_stat (const TCHAR * name, FILINFO *) { + char *path = convertSimuPath(name); struct stat tmp; - // printf("f_stat(%s)\n", path); fflush(stdout); - return stat(convertSimuPath(name), &tmp) ? FR_INVALID_NAME : FR_OK; + TRACE("f_stat(%s)", path); + return stat(path, &tmp) ? FR_INVALID_NAME : FR_OK; } FRESULT f_mount (BYTE, FATFS*) diff --git a/radio/src/targets/sky9x/diskio.cpp b/radio/src/targets/sky9x/diskio.cpp index d7f60e900..8d9ff5cfc 100644 --- a/radio/src/targets/sky9x/diskio.cpp +++ b/radio/src/targets/sky9x/diskio.cpp @@ -1014,7 +1014,7 @@ void sdMountPoll() case SD_ST_DATA: if (!usbPlugged() && f_mount(0, &g_FATFS_Obj) == FR_OK) { - refreshSystemAudioFiles(); + referenceSystemAudioFiles(); Card_state = SD_ST_MOUNTED; } break; @@ -1082,7 +1082,7 @@ void sdInit() Card_state = SD_ST_DATA; if (f_mount(0, &g_FATFS_Obj) == FR_OK) { - refreshSystemAudioFiles(); + referenceSystemAudioFiles(); Card_state = SD_ST_MOUNTED; } diff --git a/radio/src/targets/taranis/diskio.cpp b/radio/src/targets/taranis/diskio.cpp index b1d2dea7e..d9586804f 100644 --- a/radio/src/targets/taranis/diskio.cpp +++ b/radio/src/targets/taranis/diskio.cpp @@ -969,7 +969,7 @@ FIL g_telemetryFile = {0}; void sdInit() { if (f_mount(0, &g_FATFS_Obj) == FR_OK) { - refreshSystemAudioFiles(); + referenceSystemAudioFiles(); #if defined(DEBUG) f_open(&g_telemetryFile, LOGS_PATH "/sport.log", FA_OPEN_ALWAYS | FA_WRITE);