diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 672574f08..97b9a2208 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -3,7 +3,7 @@ include(Bitmaps) set(PCB_TYPES X7 X9D X9D+ X9E X10 X12S 9X 9XR 9X128 9XR128 9X2561 GRUVIN9X MEGA2560 SKY9X 9XRPRO AR9X) set(GUI_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL) -set(TTS_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU) +set(TTS_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU RU) set(PCB "X9D+" CACHE STRING "Radio type, one of: ${PCB_TYPES}") set_property(CACHE PCB PROPERTY STRINGS ${PCB_TYPES}) diff --git a/radio/src/translations.h b/radio/src/translations.h index 95e820351..6442d2798 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -843,6 +843,7 @@ extern const pm_char STR_BLCOLOR[]; extern const LanguagePack skLanguagePack; extern const LanguagePack seLanguagePack; extern const LanguagePack huLanguagePack; + extern const LanguagePack ruLanguagePack; extern const LanguagePack * const languagePacks[]; #if defined(LANGUAGE_PACKS_DEFINITION) const LanguagePack * const languagePacks[] = { @@ -856,6 +857,7 @@ extern const pm_char STR_BLCOLOR[]; &itLanguagePack, &plLanguagePack, &ptLanguagePack, + &ruLanguagePack, &seLanguagePack, &skLanguagePack, NULL diff --git a/radio/src/translations/tts_ru.cpp b/radio/src/translations/tts_ru.cpp new file mode 100644 index 000000000..f4476821c --- /dev/null +++ b/radio/src/translations/tts_ru.cpp @@ -0,0 +1,222 @@ +/* + * Author + * - Alexander Novikov (mr.pokryshkin@gmail.com) + * + * tts_ru is based on tts_de and tts_en + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "opentx.h" + +enum RusPrompts { + RU_PROMPT_NUMBERS_BASE = 0, + RU_PROMPT_ZERO = RU_PROMPT_NUMBERS_BASE+0, //02-99 + RU_PROMPT_HUNDRED = RU_PROMPT_NUMBERS_BASE+100, //100,200 .. 900 + + RU_PROMPT_AND = RU_PROMPT_NUMBERS_BASE+110, // и + RU_PROMPT_MINUS = RU_PROMPT_NUMBERS_BASE+111, // минуÑ� + RU_PROMPT_UNITS_BASE = RU_PROMPT_NUMBERS_BASE + 113, + RU_PROMPT_POINT_BASE = RU_PROMPT_NUMBERS_BASE + 165, //.0 - .9 + RU_PROMPT_FEMALE_ONE = RU_PROMPT_NUMBERS_BASE + 180, + RU_PROMPT_FEMALE_TWO = RU_PROMPT_NUMBERS_BASE + 190, + + RU_PROMPT_THOUSAND1 = RU_PROMPT_NUMBERS_BASE+200, //1000 + RU_PROMPT_THOUSAND2 = RU_PROMPT_NUMBERS_BASE+201, //2000 + RU_PROMPT_THOUSAND5 = RU_PROMPT_NUMBERS_BASE+202, //5000 +}; +#define MALE 0x00 +#define FEMALE 0x01 +#define RU_FEMALE_UNIT 0xFF + +#if defined(VOICE) + +#if defined(CPUARM) + #define RU_PUSH_UNIT_PROMPT(u, p) ru_pushUnitPrompt((u), (p), id) +#else + #define RU_PUSH_UNIT_PROMPT(u, p) pushUnitPrompt((u), (p)) +#endif + +I18N_PLAY_FUNCTION(ru, pushUnitPrompt, uint8_t unitprompt, int16_t number) +{ +#if defined(CPUARM) + if (number < 0){ // if negative number, we have to use 2 units form (for example value = 1.3) + PUSH_UNIT_PROMPT(unitprompt, 2); + } + else{ + int16_t mod10 = number % 10; + if (number == 0) + PUSH_UNIT_PROMPT(unitprompt, 0); + else if (number == 1) + PUSH_UNIT_PROMPT(unitprompt, 1); + else if (number>=2 && number <=4) + PUSH_UNIT_PROMPT(unitprompt, 2); + else if (number>=5 && number <=20) + PUSH_UNIT_PROMPT(unitprompt, 5); + else if (mod10 == 1) + PUSH_UNIT_PROMPT(unitprompt, 1); + else if (mod10 >= 2 && mod10 <=4) + PUSH_UNIT_PROMPT(unitprompt, 2); + else + PUSH_UNIT_PROMPT(unitprompt, 5); + } +#else + + // TODO: add rules for Russian language + unitprompt = RU_PROMPT_UNITS_BASE + unitprompt*4; + if (number == 1) + PUSH_NUMBER_PROMPT(unitprompt); + else + PUSH_NUMBER_PROMPT(unitprompt+1); +#endif +} + +I18N_PLAY_FUNCTION(ru, playNumber, getvalue_t number, uint8_t unit, uint8_t att) +{ + if (number < 0) { + PUSH_NUMBER_PROMPT(RU_PROMPT_MINUS); + number = -number; + } + +#if !defined(CPUARM) + if (unit) { + unit--; + convertUnit(number, unit); + if (IS_IMPERIAL_ENABLE()) { + if (unit == UNIT_DIST) { + unit = UNIT_FEET; + } + if (unit == UNIT_SPEED) { + unit = UNIT_KTS; + } + } + unit++; + } +#endif + div_t qr = div(number, 10); + int8_t mode = MODE(att); + if (mode > 0 && att != RU_FEMALE_UNIT) { +#if defined(CPUARM) + if (mode == 2) { + number /= 10; + } +#else + // we assume that we are PREC1 +#endif + if (qr.rem) { + PLAY_NUMBER(qr.quot, 0, 0); + PUSH_NUMBER_PROMPT(RU_PROMPT_POINT_BASE + qr.rem); + number = -1; + } + else { + number = qr.quot; + } + } + + int16_t tmp = number; + + if (number >= 1000) { + PLAY_NUMBER(number / 1000, RU_FEMALE_UNIT, 0); // female + uint8_t thousands = number / 1000; + int16_t mod10 = thousands % 10; + if (thousands == 1) + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND1); + else if (thousands>=2 && thousands <=4) + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND2); + else if (thousands>=5 && thousands <=20) + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND5); + else if (mod10 == 1) + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND1); + else if (mod10 >= 2 && mod10 <=4) + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND2); + else + PUSH_NUMBER_PROMPT(RU_PROMPT_THOUSAND5); + number %= 1000; + if (number == 0) + number = -1; + } + if (number >= 100) { + PUSH_NUMBER_PROMPT(RU_PROMPT_HUNDRED + (number/100)-1); + number %= 100; + if (number == 0) + number = -1; + } + if (number >= 0) { + uint8_t attr = MALE; + switch(unit) { + case RU_FEMALE_UNIT: + case UNIT_MPH: + case UNIT_FLOZ: + case UNIT_MINUTES: + case UNIT_SECONDS: + attr = FEMALE; + break; + default: + attr = MALE; + break; + } + uint8_t lastDigit = number % 10; + uint8_t ten=(number - (number % 10))/10; + if (lastDigit == 1 && number != 11 && attr == FEMALE) + PUSH_NUMBER_PROMPT(RU_PROMPT_FEMALE_ONE + ten); + else if (lastDigit == 2 && number !=12 && attr == FEMALE) + PUSH_NUMBER_PROMPT(RU_PROMPT_FEMALE_TWO + ten); + else + PUSH_NUMBER_PROMPT(RU_PROMPT_ZERO + number); + } + + if (unit) { + if (mode > 0 && qr.rem) // number with decimal point + RU_PUSH_UNIT_PROMPT(unit, -1); // force 2 units form, if float value + else + RU_PUSH_UNIT_PROMPT(unit, tmp); + } +} + +I18N_PLAY_FUNCTION(ru, playDuration, int seconds PLAY_DURATION_ATT) +{ + if (seconds == 0) { + PLAY_NUMBER(seconds, 0, 0); + return; + } + + if (seconds < 0) { + PUSH_NUMBER_PROMPT(RU_PROMPT_MINUS); + seconds = -seconds; + } + + uint8_t tmp = seconds / 3600; + seconds %= 3600; + if (tmp > 0 || IS_PLAY_TIME()) { + PLAY_NUMBER(tmp, UNIT_HOURS, 0); + } + + tmp = seconds / 60; + seconds %= 60; + if (tmp > 0) { + PLAY_NUMBER(tmp, UNIT_MINUTES, 0); + if (seconds > 0) + PUSH_NUMBER_PROMPT(RU_PROMPT_AND); + } + if (seconds > 0) { + PLAY_NUMBER(seconds, UNIT_SECONDS, 0); + } +} + +LANGUAGE_PACK_DECLARE(ru, "Russian"); + +#endif diff --git a/radio/util/voices_ru.psv b/radio/util/voices_ru.psv new file mode 100644 index 000000000..45134c023 --- /dev/null +++ b/radio/util/voices_ru.psv @@ -0,0 +1,272 @@ +SYSTEM|0000|0 +SYSTEM|0001|1 +SYSTEM|0002|2 +SYSTEM|0003|3 +SYSTEM|0004|4 +SYSTEM|0005|5 +SYSTEM|0006|6 +SYSTEM|0007|7 +SYSTEM|0008|8 +SYSTEM|0009|9 +SYSTEM|0010|10 +SYSTEM|0011|11 +SYSTEM|0012|12 +SYSTEM|0013|13 +SYSTEM|0014|14 +SYSTEM|0015|15 +SYSTEM|0016|16 +SYSTEM|0017|17 +SYSTEM|0018|18 +SYSTEM|0019|19 +SYSTEM|0020|20 +SYSTEM|0021|21 +SYSTEM|0022|22 +SYSTEM|0023|23 +SYSTEM|0024|24 +SYSTEM|0025|25 +SYSTEM|0026|26 +SYSTEM|0027|27 +SYSTEM|0028|28 +SYSTEM|0029|29 +SYSTEM|0030|30 +SYSTEM|0031|31 +SYSTEM|0032|32 +SYSTEM|0033|33 +SYSTEM|0034|34 +SYSTEM|0035|35 +SYSTEM|0036|36 +SYSTEM|0037|37 +SYSTEM|0038|38 +SYSTEM|0039|39 +SYSTEM|0040|40 +SYSTEM|0041|41 +SYSTEM|0042|42 +SYSTEM|0043|43 +SYSTEM|0044|44 +SYSTEM|0045|45 +SYSTEM|0046|46 +SYSTEM|0047|47 +SYSTEM|0048|48 +SYSTEM|0049|49 +SYSTEM|0050|50 +SYSTEM|0051|51 +SYSTEM|0052|52 +SYSTEM|0053|53 +SYSTEM|0054|54 +SYSTEM|0055|55 +SYSTEM|0056|56 +SYSTEM|0057|57 +SYSTEM|0058|58 +SYSTEM|0059|59 +SYSTEM|0060|60 +SYSTEM|0061|61 +SYSTEM|0062|62 +SYSTEM|0063|63 +SYSTEM|0064|64 +SYSTEM|0065|65 +SYSTEM|0066|66 +SYSTEM|0067|67 +SYSTEM|0068|68 +SYSTEM|0069|69 +SYSTEM|0070|70 +SYSTEM|0071|71 +SYSTEM|0072|72 +SYSTEM|0073|73 +SYSTEM|0074|74 +SYSTEM|0075|75 +SYSTEM|0076|76 +SYSTEM|0077|77 +SYSTEM|0078|78 +SYSTEM|0079|79 +SYSTEM|0080|80 +SYSTEM|0081|81 +SYSTEM|0082|82 +SYSTEM|0083|83 +SYSTEM|0084|84 +SYSTEM|0085|85 +SYSTEM|0086|86 +SYSTEM|0087|87 +SYSTEM|0088|88 +SYSTEM|0089|89 +SYSTEM|0090|90 +SYSTEM|0091|91 +SYSTEM|0092|92 +SYSTEM|0093|93 +SYSTEM|0094|94 +SYSTEM|0095|95 +SYSTEM|0096|96 +SYSTEM|0097|97 +SYSTEM|0098|98 +SYSTEM|0099|99 +SYSTEM|0100|100 +SYSTEM|0101|200 +SYSTEM|0102|300 +SYSTEM|0103|400 +SYSTEM|0104|500 +SYSTEM|0105|600 +SYSTEM|0106|700 +SYSTEM|0107|800 +SYSTEM|0108|900 +SYSTEM|0109|1000 +SYSTEM|0110|è +SYSTEM|0111|ìèíóñ +SYSTEM|0112| +SYSTEM|0165|ðîâíî +SYSTEM|0166|è îäíà äåñÿòàÿ +SYSTEM|0167|è äâå äåñÿòûõ +SYSTEM|0168|è òðè äåñÿòûõ +SYSTEM|0169|è ÷åòûðå äåñÿòûõ +SYSTEM|0170|è ïÿòü äåñÿòûõ +SYSTEM|0171|è øåñòü äåñÿòûõ +SYSTEM|0172|è ñåìü äåñÿòûõ +SYSTEM|0173|è âîñåìü äåñÿòûõ +SYSTEM|0174|è äåâÿòü äåñÿòûõ +SYSTEM|volt0|âîëüò +SYSTEM|volt1|âîëüò +SYSTEM|volt2|âîëüòà +SYSTEM|volt5|âîëüò +SYSTEM|amp0|àìïåð +SYSTEM|amp1|àìïåð +SYSTEM|amp2|àìïåðà +SYSTEM|amp5|àìïåð +SYSTEM|mamp0|ìèëëèàìïåð +SYSTEM|mamp1|ìèëëèàìïåð +SYSTEM|mamp2|ìèëëèàìïåðà +SYSTEM|mamp5|ìèëëèàìïåð +SYSTEM|knot0|óçëîâ +SYSTEM|knot1|óçåë +SYSTEM|knot2|óçëà +SYSTEM|knot5|óçëîâ +SYSTEM|mps0|ìåòðîâ â ñåêóíäó +SYSTEM|mps1|ìåòð â ñåêóíäó +SYSTEM|mps2|ìåòðà â ñåêóíäó +SYSTEM|mps5|ìåòðîâ â ñåêóíäó +SYSTEM|celsius0|ãðàäóñîâ +SYSTEM|celsius1|ãðàäóñ +SYSTEM|celsius2|ãðàäóñà +SYSTEM|celsius5|ãðàäóñîâ +SYSTEM|db0|äåöèáåë +SYSTEM|db1|äåöèáåë +SYSTEM|db2|äåöèáåëà +SYSTEM|db5|äåöèáåë +SYSTEM|degree0|ãðàäóñîâ +SYSTEM|degree1|ãðàäóñ +SYSTEM|degree2|ãðàäóñà +SYSTEM|degree5|ãðàäóñîâ +SYSTEM|fahr0|ãðàäóñîâ ïî ôàðåíãåéòó +SYSTEM|fahr1|ãðàäóñ ïî ôàðåíãåéòó +SYSTEM|fahr2|ãðàäóñà ïî ôàðåíãåéòó +SYSTEM|fahr5|ãðàäóñîâ ïî ôàðåíãåéòó +SYSTEM|foot0|ôóòîâ +SYSTEM|foot1|ôóò +SYSTEM|foot2|ôóòà +SYSTEM|foot5|ôóòîâ +SYSTEM|founce0|óíöèé +SYSTEM|founce1|óíöèÿ +SYSTEM|founce2|óíöèè +SYSTEM|founce5|óíöèé +SYSTEM|fps0|ôóòîâ â ñåêóíäó +SYSTEM|fps1|ôóò â ñåêóíäó +SYSTEM|fps2|ôóòà â ñåêóíäó +SYSTEM|fps5|ôóòîâ â ñåêóíäó +SYSTEM|g0|äæè +SYSTEM|g1|äæè +SYSTEM|g2|äæè +SYSTEM|g5|äæè +SYSTEM|hour0|÷àñîâ +SYSTEM|hour1|÷àñ +SYSTEM|hour2|÷àñà +SYSTEM|hour5|÷àñîâ +SYSTEM|kph0|êèëîìåòðîâ â ÷àñ +SYSTEM|kph1|êèëîìåòð â ÷àñ +SYSTEM|kph2|êèëîìåòðà â ÷àñ +SYSTEM|kph5|êèëîìåòðîâ â ÷àñ +SYSTEM|mamph0|ìèëëèàìïåð â ÷àñ +SYSTEM|mamph1|ìèëëèàìïåð â ÷àñ +SYSTEM|mamph2|ìèëëèàìïåðà â ÷àñ +SYSTEM|mamph5|ìèëëèàìïåð â ÷àñ +SYSTEM|meter0|ìåòðîâ +SYSTEM|meter1|ìåòð +SYSTEM|meter2|ìåòðà +SYSTEM|meter5|ìåòðîâ +SYSTEM|minute0|ìèíóò +SYSTEM|minute1|ìèíóòà +SYSTEM|minute2|ìèíóòû +SYSTEM|minute5|ìèíóò +SYSTEM|ml0|ìèëëèëèòðîâ +SYSTEM|ml1|ìèëëèëèòð +SYSTEM|ml2|ìèëëèëèòðà +SYSTEM|ml5|ìèëëèëèòðîâ +SYSTEM|mph0|ìèëü â ÷àñ +SYSTEM|mph1|ìèëÿ â ÷àñ +SYSTEM|mph2|ìèëè â ÷àñ +SYSTEM|mph5|ìèëü â ÷àñ +SYSTEM|mwatt0|ìèëëèâàòò +SYSTEM|mwatt1|ìèëëèâàòò +SYSTEM|mwatt2|ìèëëèâàòòà +SYSTEM|mwatt5|ìèëëèâàòò +SYSTEM|percent0|ïðîöåíòîâ +SYSTEM|percent1|ïðîöåíò +SYSTEM|percent2|ïðîöåíòà +SYSTEM|percent5|ïðîöåíòîâ +SYSTEM|radian0|ðàäèàí +SYSTEM|radian1|ðàäèàí +SYSTEM|radian2|ðàäèàíà +SYSTEM|radian5|ðàäèàí +SYSTEM|rpm0|îáîðîòîâ â ìèíóòó +SYSTEM|rpm1|îáîðîò â ìèíóòó +SYSTEM|rpm2|îáîðîòà â ìèíóòó +SYSTEM|rpm5|îáîðîòîâ â ìèíóòó +SYSTEM|second0|ñåêóíä +SYSTEM|second1|ñåêóíäà +SYSTEM|second2|ñåêóíäû +SYSTEM|second5|ñåêóíä +SYSTEM|watt0|âàòò +SYSTEM|watt1|âàòò +SYSTEM|watt2|âàòòà +SYSTEM|watt5|âàòò +SYSTEM|eebad|Îøèáêà ïàìÿòè +SYSTEM|hello|Òàêè çäðàâñòâóéòå! +SYSTEM|inactiv|ß òóò! Ïðî ìåíÿ çàáûëè! +SYSTEM|lowbatt|Àêêóìóëÿòîð ðàçðÿæåí +SYSTEM|maxtrim|Òðèììåð ìàêñèìóì +SYSTEM|midtrim|Òðèììåð ïî öåíòðó +SYSTEM|mintrim|Òðèììåð ìèíèìóì +SYSTEM|rssi_org|Ñëàáûé ñèãíàë! +SYSTEM|rssi_red|Î÷åíü ñëàáûé ñèãíàë! +SYSTEM|rxko| +SYSTEM|sensorko|Ñåíñîð îòêëþ÷åí +SYSTEM|servoko| +SYSTEM|swalert|Ïðîâåðü òóìáëåðû! +SYSTEM|swr_red|Ïðîáëåìû ñ àíòåííîé ïåðåäàò÷èêà! +SYSTEM|telemko|Ïîòåðÿí ñèãíàë òåëåìåòðèè +SYSTEM|telemok|Òåëåìåòðèÿ âîññòàíîâëåíà +SYSTEM|thralert|Óáåðè ãàç! +SYSTEM|timovr1|Òàéìåð 1. Âðåìÿ âûøëî +SYSTEM|timovr2|Òàéìåð 2. Âðåìÿ âûøëî +SYSTEM|timovr3|Òàéìåð 3. Âðåìÿ âûøëî +SYSTEM|trainko|Òðåíåðñêèé ñèãíàë ïîòåðÿí +SYSTEM|trainok|Ïîÿâèëñÿ òðåíåðñêèé ñèãíàë +SYSTEM|0180|îäíà +SYSTEM|0181|îäèííàäöàòü +SYSTEM|0182|äâàäöàòü îäíà +SYSTEM|0183|òðèäöàòü îäíà +SYSTEM|0184|ñîðîê îäíà +SYSTEM|0185|ïÿòüäåñÿò îäíà +SYSTEM|0186|øåñòüäåñÿò îäíà +SYSTEM|0187|ñåìüäåñÿò îäíà +SYSTEM|0188|âîñåìüäåñÿò îäíà +SYSTEM|0189|äåâÿíîñòî îäíà +SYSTEM|0190|äâå +SYSTEM|0191|äâåíàäöàòü +SYSTEM|0192|äâàäöàòü äâå +SYSTEM|0193|òðèäöàòü äâå +SYSTEM|0194|ñîðîê äâå +SYSTEM|0195|ïÿòüäåñÿò äâå +SYSTEM|0196|øåñòüäåñÿò äâå +SYSTEM|0197|ñåìüäåñÿò äâå +SYSTEM|0198|âîñåìüäåñÿò äâå +SYSTEM|0199|äåâÿíîñòî äâå +SYSTEM|0200|òûñÿ÷à +SYSTEM|0201|òûñÿ÷è +SYSTEM|0202|òûñÿ÷