quite a lot of stuff, can't list them all here (approaching 1.9)

This commit is contained in:
2026-04-25 18:13:09 +02:00
parent d79c238924
commit 4b904bc720
20 changed files with 639 additions and 628 deletions
+230 -237
View File
@@ -2,245 +2,239 @@ import unicodedata
# This script prepares the RDS charset conversion function
# RDS code to UCS-2
charset = {}
# The data comes directly from the rdscharset.pdf, which comes from the R22_039_1 standard
data = """33 0x21 ! 0x0021 EXCLAMATION MARK
34 0x22 " 0x0022 QUOTATION MARK
35 0x23 # 0x0023 NUMBER SIGN
36 0x24 ¤ 0x00A4 CURRENCY SIGN
37 0x25 % 0x0025 PERCENT SIGN
38 0x26 & 0x0026 AMPERSAND
39 0x27 ' 0x0027 APOSTROPHE
40 0x28 ( 0x0028 LEFT PARENTHESIS
41 0x29 ) 0x0029 RIGHT PARENTHESIS
42 0x2A * 0x002A ASTERISK
43 0x2B + 0x002B PLUS SIGN
44 0x2C , 0x002C COMMA
45 0x2D - 0x002D HYPHEN-MINUS
46 0x2E . 0x002E FULL STOP
47 0x2F / 0x002F SOLIDUS
48 0x30 0 0x0030 DIGIT ZERO
49 0x31 1 0x0031 DIGIT ONE
50 0x32 2 0x0032 DIGIT TWO
51 0x33 3 0x0033 DIGIT THREE
52 0x34 4 0x0034 DIGIT FOUR
53 0x35 5 0x0035 DIGIT FIVE
54 0x36 6 0x0036 DIGIT SIX
55 0x37 7 0x0037 DIGIT SEVEN
56 0x38 8 0x0038 DIGIT EIGHT
57 0x39 9 0x0039 DIGIT NINE
58 0x3A : 0x003A COLON
59 0x3B ; 0x003B SEMICOLON
60 0x3C < 0x003C LESS-THAN SIGN
61 0x3D = 0x003D EQUALS SIGN
62 0x3E > 0x003E GREATER-THAN SIGN
63 0x3F ? 0x003F QUESTION MARK
64 0x40 @ 0x0040 COMMERCIAL AT
65 0x41 A 0x0041 LATIN CAPITAL LETTER A
66 0x42 B 0x0042 LATIN CAPITAL LETTER B
67 0x43 C 0x0043 LATIN CAPITAL LETTER C
68 0x44 D 0x0044 LATIN CAPITAL LETTER D
69 0x45 E 0x0045 LATIN CAPITAL LETTER E
70 0x46 F 0x0046 LATIN CAPITAL LETTER F
71 0x47 G 0x0047 LATIN CAPITAL LETTER G
72 0x48 H 0x0048 LATIN CAPITAL LETTER H
73 0x49 I 0x0049 LATIN CAPITAL LETTER I
74 0x4A J 0x004A LATIN CAPITAL LETTER J
75 0x4B K 0x004B LATIN CAPITAL LETTER K
76 0x4C L 0x004C LATIN CAPITAL LETTER L
77 0x4D M 0x004D LATIN CAPITAL LETTER M
78 0x4E N 0x004E LATIN CAPITAL LETTER N
79 0x4F O 0x004F LATIN CAPITAL LETTER O
80 0x50 P 0x0050 LATIN CAPITAL LETTER P
81 0x51 Q 0x0051 LATIN CAPITAL LETTER Q
82 0x52 R 0x0052 LATIN CAPITAL LETTER R
83 0x53 S 0x0053 LATIN CAPITAL LETTER S
84 0x54 T 0x0054 LATIN CAPITAL LETTER T
85 0x55 U 0x0055 LATIN CAPITAL LETTER U
86 0x56 V 0x0056 LATIN CAPITAL LETTER V
87 0x57 W 0x0057 LATIN CAPITAL LETTER W
88 0x58 X 0x0058 LATIN CAPITAL LETTER X
89 0x59 Y 0x0059 LATIN CAPITAL LETTER Y
90 0x5A Z 0x005A LATIN CAPITAL LETTER Z
91 0x5B [ 0x005B LEFT SQUARE BRACKET
92 0x5C \\ 0x005C REVERSE SOLIDUS
93 0x5D ] 0x005D RIGHT SQUARE BRACKET
94 0x5E ― 0x2015 HORIZONTAL BAR
95 0x5F _ 0x005F LOW LINE
96 0x60 ║ 0x2016 DOUBLE VERTICAL LINE
97 0x61 a 0x0061 LATIN SMALL LETTER A
98 0x62 b 0x0062 LATIN SMALL LETTER B
99 0x63 c 0x0063 LATIN SMALL LETTER C
100 0x64 d 0x0064 LATIN SMALL LETTER D
101 0x65 e 0x0065 LATIN SMALL LETTER E
102 0x66 f 0x0066 LATIN SMALL LETTER F
103 0x67 g 0x0067 LATIN SMALL LETTER G
104 0x68 h 0x0068 LATIN SMALL LETTER H
105 0x69 i 0x0069 LATIN SMALL LETTER I
106 0x6A j 0x006A LATIN SMALL LETTER J
107 0x6B k 0x006B LATIN SMALL LETTER K
108 0x6C l 0x006C LATIN SMALL LETTER L
109 0x6D m 0x006D LATIN SMALL LETTER M
110 0x6E n 0x006E LATIN SMALL LETTER N
111 0x6F o 0x006F LATIN SMALL LETTER O
112 0x70 p 0x0070 LATIN SMALL LETTER P
113 0x71 q 0x0071 LATIN SMALL LETTER Q
114 0x72 r 0x0072 LATIN SMALL LETTER R
115 0x73 s 0x0073 LATIN SMALL LETTER S
116 0x74 t 0x0074 LATIN SMALL LETTER T
117 0x75 u 0x0075 LATIN SMALL LETTER U
118 0x76 v 0x0076 LATIN SMALL LETTER V
119 0x77 w 0x0077 LATIN SMALL LETTER W
120 0x78 x 0x0078 LATIN SMALL LETTER X
121 0x79 y 0x0079 LATIN SMALL LETTER Y
122 0x7A z 0x007A LATIN SMALL LETTER Z
123 0x7B { 0x007B LEFT CURLY BRACKET
124 0x7C | 0x007C VERTICAL LINE
125 0x7D } 0x007D RIGHT CURLY BRACKET
126 0x7E ¯ 0x203E OVERLINE
128 0x80 á 0x00E1 LATIN SMALL LETTER A WITH ACUTE
129 0x81 à 0x00E0 LATIN SMALL LETTER A WITH GRAVE
130 0x82 é 0x00E9 LATIN SMALL LETTER E WITH ACUTE
131 0x83 è 0x00E8 LATIN SMALL LETTER E WITH GRAVE
132 0x84 í 0x00ED LATIN SMALL LETTER I WITH ACUTE
133 0x85 ì 0x00EC LATIN SMALL LETTER I WITH GRAVE
134 0x86 ó 0x00F3 LATIN SMALL LETTER O WITH ACUTE
135 0x87 ò 0x00F2 LATIN SMALL LETTER O WITH GRAVE
136 0x88 ú 0x00FA LATIN SMALL LETTER U WITH ACUTE
137 0x89 ù 0x00F9 LATIN SMALL LETTER U WITH GRAVE
138 0x8A Ñ 0x00D1 LATIN CAPITAL LETTER N WITH TILDE
139 0x8B Ç 0x00C7 LATIN CAPITAL LETTER C WITH CEDILLA
140 0x8C Ş 0x015E LATIN CAPITAL LETTER S WITH CEDILLA
141 0x8D ß 0x00DF LATIN SMALL LETTER SHARP S (German)
142 0x8E ¡ 0x00A1 INVERTED EXCLAMATION MARK
143 0x8F IJ 0x0132 LATIN CAPITAL LIGATURE IJ
144 0x90 â 0x00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
145 0x91 ä 0x00E4 LATIN SMALL LETTER A WITH DIAERESIS
146 0x92 ê 0x00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
147 0x93 ë 0x00EB LATIN SMALL LETTER E WITH DIAERESIS
148 0x94 î 0x00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
149 0x95 ï 0x00EF LATIN SMALL LETTER I WITH DIAERESIS
150 0x96 ô 0x00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
151 0x97 ö 0x00F6 LATIN SMALL LETTER O WITH DIAERESIS
152 0x98 û 0x00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
153 0x99 ü 0x00FC LATIN SMALL LETTER U WITH DIAERESIS
154 0x9A ñ 0x00F1 LATIN SMALL LETTER N WITH TILDE
155 0x9B ç 0x00E7 LATIN SMALL LETTER C WITH CEDILLA
156 0x9C ş 0x015F LATIN SMALL LETTER S WITH CEDILLA
157 0x9D ğ 0x011F LATIN SMALL LETTER G WITH BREVE
158 0x9E ı 0x0131 LATIN SMALL LETTER DOTLESS I
159 0x9F ij 0x0133 LATIN SMALL LIGATURE IJ
160 0xA0 ª 0x00AA FEMININE ORDINAL INDICATOR
161 0xA1 α 0x03B1 GREEK SMALL LETTER ALPHA
162 0xA2 © 0x00A9 COPYRIGHT SIGN
163 0xA3 ‰ 0x2030 PER THOUSAND SIGN
164 0xA4 Ğ 0x011E LATIN CAPITAL LETTER G WITH BREVE
165 0xA5 ĕ 0x011B LATIN SMALL LETTER WITH CARON
166 0xA6 ň 0x0148 LATIN SMALL LETTER N WITH CARON
167 0xA7 ő 0x0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE
168 0xA8 π 0x03C0 GREEK SMALL LETTER PI
169 0xA9 € 0x20AC EURO SIGN
170 0xAA ₤ 0x00A3 POUND SIGN
171 0xAB $ 0x0024 DOLLAR SIGN
172 0xAC ← 0x2190 LEFTWARDS ARROW
173 0xAD ↑ 0x2191 UPWARDS ARROW
174 0xAE → 0x2192 RIGHTWARDS ARROW
175 0xAF ↓ 0x2193 DOWNWARDS ARROW
176 0xB0 º 0x00BA MASCULIN ORDINAL INDICATOR
177 0xB1 ¹ 0x00B9 SUPERSCRIPT ONE
178 0xB2 ² 0x00B2 SUPERSCRIPT TWO
179 0xB3 ³ 0x00B3 SUPERSCRIPT THREE
180 0xB4 ± 0x00B1 PLUS-MINUS SIGN
181 0xB5 İ 0x0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
182 0xB6 ń 0x0144 LATIN SMALL LETTER N WITH ACUTE
183 0xB7 ű 0x0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE
184 0xB8 µ 0x00B5 MIKRO SIGN
185 0xB9 ¿ 0x00BF INVERTED QUESTION MARK
186 0xBA ÷ 0x00F7 DIVISION SIGN
187 0xBB º 0x00B0 DEGREE SIGN
188 0xBC ¼ 0x00BC VULGAR FRACTION ONE QUARTER
189 0xBD ½ 0x00BD VULGAR FRACTION ONE HALF
190 0xBE ¾ 0x00BE VULGAR FRACTION THREE QUARTERS
191 0xBF § 0x00A7 SECTION SIGN
192 0xC0 Á 0x00C1 LATIN CAPITAL LETTER A WITH ACUTE
193 0xC1 À 0x00C0 LATIN CAPITAL LETTER A WITH GRAVE
194 0xC2 É 0x00C9 LATIN CAPITAL LETTER E WITH ACUTE
195 0xC3 È 0x00C8 LATIN CAPITAL LETTER E WITH GRAVE
196 0xC4 Í 0x00CD LATIN CAPITAL LETTER I WITH ACUTE
197 0xC5 Ì 0x00CC LATIN CAPITAL LETTER I WITH GRAVE
198 0xC6 Ó 0x00D3 LATIN CAPITAL LETTER O WITH ACUTE
199 0xC7 Ò 0x00D2 LATIN CAPITAL LETTER O WITH GRAVE
200 0xC8 Ú 0x00DA LATIN CAPITAL LETTER U WITH ACUTE
201 0xC9 Ù 0x00D9 LATIN CAPITAL LETTER U WITH GRAVE
202 0xCA Ř 0x0158 LATIN CAPITAL LETTER R WITH CARON
203 0xCB Č 0x010C LATIN CAPITAL LETTER C WITH CARON
204 0xCC Š 0x0160 LATIN CAPITAL LETTER S WITH CARON
205 0xCD Ž 0x017D LATIN CAPITAL LETTER Z WITH CARON
206 0xCE Ð 0x00D0 LATIN CAPITAL LETTER ETH
207 0xCF Ŀ 0x013F LATIN CAPITAL LETTER L WITH MIDDLE DOT
208 0xD0 Â 0x00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
209 0xD1 Ä 0x00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
210 0xD2 Ê 0x00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX
211 0xD3 Ë 0x00CB LATIN CAPITAL LETTER A WITH DIAERESIS
212 0xD4 Î 0x00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX
213 0xD5 Ï 0x00CF LATIN CAPITAL LETTER I WITH DIAERESIS
214 0xD6 Ô 0x00D4
215 0xD7 Ö 0x00D6
216 0xD8 Û 0x00DB
217 0xD9 Ü 0x00DC
218 0xDA ř 0x0159
219 0xDB č 0x010D
220 0xDC š 0x0161
221 0xDD ž 0x017E
222 0xDE đ 0x0111
223 0xDF ŀ 0x0140
224 0xE0 Ã 0x00C3
225 0xE1 Å 0x00C5
226 0xE2 Æ 0x00C6
227 0xE3 Œ 0x0152
228 0xE4 ŷ 0x0177
229 0xE5 Ý 0x00DD
230 0xE6 Õ 0x00D5
231 0xE7 Ø 0x00D8
232 0xE8 Þ 0x00DE
233 0xE9 Ŋ 0x014A
234 0xEA Ŕ 0x0154
235 0xEB Ć 0x0106
236 0xEC Ś 0x015A
237 0xED Ź 0x0179
238 0xEE Ŧ 0x0166
239 0xEF ð 0x00F0
240 0xF0 ã 0x00E3
241 0xF1 å 0x00E5
242 0xF2 æ 0x00E6
243 0xF3 œ 0x0153
244 0xF4 ŵ 0x0175
245 0xF5 ý 0x00FD
246 0xF6 õ 0x00F5
247 0xF7 ø 0x00F8
248 0xF8 þ 0x00FE
249 0xF9 ŋ 0x014B
250 0xFA ŕ 0x0155
251 0xFB ć 0x0107
252 0xFC ś 0x015B
253 0xFD ź 0x017A
254 0xFE ŧ 0x0167
"""
for line in data.splitlines():
parts = line.split()
num, rds_code, symbol, ucs2, *_ = parts
code = int(rds_code, 16)
ucs = int(ucs2, 16)
if code != ucs: charset[code] = ucs
charset = {
0x0A: 0x0A,
0x0D: 0x0D,
0x1F: 0x1F,
0x20: 0x20,
0x21: 0x21,
0x22: 0x22,
0x23: 0x23,
0x24: 0xA4,
0x25: 0x25,
0x26: 0x26,
0x27: 0x27,
0x28: 0x28,
0x29: 0x29,
0x2A: 0x2A,
0x2B: 0x2B,
0x2C: 0x2C,
0x2D: 0x2D,
0x2E: 0x2E,
0x2F: 0x2F,
0x30: 0x30,
0x31: 0x31,
0x32: 0x32,
0x33: 0x33,
0x34: 0x34,
0x35: 0x35,
0x36: 0x36,
0x37: 0x37,
0x38: 0x38,
0x39: 0x39,
0x3A: 0x3A,
0x3B: 0x3B,
0x3C: 0x3C,
0x3D: 0x3D,
0x3E: 0x3E,
0x3F: 0x3F,
0x40: 0x40,
0x41: 0x41,
0x42: 0x42,
0x43: 0x43,
0x44: 0x44,
0x45: 0x45,
0x46: 0x46,
0x47: 0x47,
0x48: 0x48,
0x49: 0x49,
0x4A: 0x4A,
0x4B: 0x4B,
0x4C: 0x4C,
0x4D: 0x4D,
0x4E: 0x4E,
0x4F: 0x4F,
0x50: 0x50,
0x51: 0x51,
0x52: 0x52,
0x53: 0x53,
0x54: 0x54,
0x55: 0x55,
0x56: 0x56,
0x57: 0x57,
0x58: 0x58,
0x59: 0x59,
0x5A: 0x5A,
0x5B: 0x5B,
0x5C: 0x5C,
0x5D: 0x5D,
0x5E: 0x2015,
0x5F: 0x005F,
0x60: 0x2016,
0x61: 0x61,
0x62: 0x62,
0x63: 0x63,
0x64: 0x64,
0x65: 0x65,
0x66: 0x66,
0x67: 0x67,
0x68: 0x68,
0x69: 0x69,
0x6A: 0x6A,
0x6B: 0x6B,
0x6C: 0x6C,
0x6D: 0x6D,
0x6E: 0x6E,
0x6F: 0x6F,
0x70: 0x70,
0x71: 0x71,
0x72: 0x72,
0x73: 0x73,
0x74: 0x74,
0x75: 0x75,
0x76: 0x76,
0x77: 0x77,
0x78: 0x78,
0x79: 0x79,
0x7A: 0x7A,
0x7B: 0x7B,
0x7C: 0x7C,
0x7D: 0x7D,
0x7E: 0x203E,
0x80: 0xE1,
0x81: 0xE0,
0x82: 0xE9,
0x83: 0xE8,
0x84: 0xED,
0x85: 0xEC,
0x86: 0xF3,
0x87: 0xF2,
0x88: 0xFA,
0x89: 0xF9,
0x8A: 0xD1,
0x8B: 0xC7,
0x8C: 0x15E,
0x8D: 0xDF,
0x8E: 0xA1,
0x8F: 0x132,
0x90: 0xE2,
0x91: 0xE4,
0x92: 0xEA,
0x93: 0xEB,
0x94: 0xEE,
0x95: 0xEF,
0x96: 0xF4,
0x97: 0xF6,
0x98: 0xFB,
0x99: 0xFC,
0x9A: 0xF1,
0x9B: 0xE7,
0x9C: 0x15F,
0x9D: 0x11F,
0x9E: 0x131,
0x9F: 0x133,
0xA0: 0xAA,
0xA1: 0x3B1,
0xA2: 0xA9,
0xA3: 0x2030,
0xA4: 0x11E,
0xA5: 0x11B,
0xA6: 0x148,
0xA7: 0x151,
0xA8: 0x3C0,
0xA9: 0x20AC,
0xAA: 0xA3,
0xAB: 0x24,
0xAC: 0x2190,
0xAD: 0x2191,
0xAE: 0x2192,
0xAF: 0x2193,
0xB0: 0xBA,
0xB1: 0xB9,
0xB2: 0xB2,
0xB3: 0xB3,
0xB4: 0xB1,
0xB5: 0x130,
0xB6: 0x144,
0xB7: 0x171,
0xB8: 0xB5,
0xB9: 0xBF,
0xBA: 0xF7,
0xBB: 0xB0,
0xBC: 0xBC,
0xBD: 0xBD,
0xBE: 0xBE,
0xBF: 0xA7,
0xC0: 0xC1,
0xC1: 0xC0,
0xC2: 0xC9,
0xC3: 0xC8,
0xC4: 0xCD,
0xC5: 0xCC,
0xC6: 0xD3,
0xC7: 0xD2,
0xC8: 0xDA,
0xC9: 0xD9,
0xCA: 0x158,
0xCB: 0x10C,
0xCC: 0x160,
0xCD: 0x17D,
0xCE: 0xD0,
0xCF: 0x13F,
0xD0: 0xC2,
0xD1: 0xC4,
0xD2: 0xCA,
0xD3: 0xCB,
0xD4: 0xCE,
0xD5: 0xCF,
0xD6: 0xD4,
0xD7: 0xD6,
0xD8: 0xDB,
0xD9: 0xDC,
0xDA: 0x159,
0xDB: 0x10D,
0xDC: 0x161,
0xDD: 0x17E,
0xDE: 0x111,
0xDF: 0x140,
0xE0: 0xC3,
0xE1: 0xC5,
0xE2: 0xC6,
0xE3: 0x152,
0xE4: 0x177,
0xE5: 0xDD,
0xE6: 0xD5,
0xE7: 0xD8,
0xE8: 0xDE,
0xE9: 0x14A,
0xEA: 0x154,
0xEB: 0x106,
0xEC: 0x15A,
0xED: 0x179,
0xEE: 0x166,
0xEF: 0xF0,
0xF0: 0xE3,
0xF1: 0xE5,
0xF2: 0xE6,
0xF3: 0x153,
0xF4: 0x175,
0xF5: 0xFD,
0xF6: 0xF5,
0xF7: 0xF8,
0xF8: 0x0FE,
0xF9: 0x14B,
0xFA: 0x155,
0xFB: 0x107,
0xFC: 0x15B,
0xFD: 0x17A,
0xFE: 0x167}
table = {}
import struct
for rds_code, ucs2 in charset.items():
utf8 = struct.pack("!H", ucs2).decode("utf-16-be").encode()
utf8 = struct.pack("!H", ucs2).decode("utf-16-be").encode("utf-8")
node = table
for i, byte in enumerate(utf8):
@@ -263,10 +257,9 @@ def generate_switch(node, indent=0, level=0):
code_lines.extend(generate_switch(child, indent + 2, level + 1))
code_lines.append(f"{ind}\t\tbreak;")
else:
comment = unicodedata.name(struct.pack("!H", charset[child]).decode("utf-16-be"))
code_lines.append(f"{ind}\tcase (char)0x{byte:02x}: new_str[i] = (char)0x{child:02x}; break; // {comment}")
if level == 0: code_lines.append(f"{ind}\tdefault: new_str[i] = *str; break;")
else: code_lines.append(f"{ind}\tdefault: new_str[i] = (char)0x3f; break; // {unicodedata.name("?")}") # Question mark
comment = unicodedata.name(struct.pack("!H", charset[child]).decode("utf-16-be"), "N/A")
code_lines.append(f"{ind}\tcase (char)0x{byte:02x}: output[i] = (char)0x{child:02x}; break; // {comment}")
code_lines.append(f"{ind}\tdefault: output[i] = (char)0x3f; break; // {unicodedata.name("?")}") # Question mark
code_lines.append(f"{ind}}}")
return code_lines
+49 -21
View File
@@ -1,10 +1,10 @@
---@meta
---@type string
core_version = ""
dp = {}
---@type string
dp.core_version = ""
---@type integer
dp.max_programs = 0
@@ -17,7 +17,7 @@ function dp.crc16(data) end
---@return nil
function dp.set_program_defaults() end
---Saves, loads and resets the state of the data, you might as well restart the whole program
---Saves, loads and resets the state of the data, you might as well restart the whole program. this does NOT cause data loss other than the current internal state
---@return nil
function dp.reset_rds() end
@@ -37,40 +37,62 @@ function dp.set_writing_program(program_idx) end
---@return integer
function dp.get_writing_program() end
---Encodes the given UTF-8 string into the unnamed RDS character set
---@param data string
---@return string
function dp.encode_charset(data) end
hooks = {}
---This function is called by the C core after we reset data, or have no data in general
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.on_init = {}
---This function is called by the C core after we initialize the encoder (always, every start)
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.on_start = {}
---This function is called every time when the state resets, register your odas here
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.on_state = {}
---This function is called every second
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.tick = {}
---This function is calld every time a RT transmits start to end - Useful for UECP's RT buffer shenanigans
---This function is called every minute
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.minute_tick = {}
---This function is called every time a RT transmits start to end - Useful for UECP's RT buffer shenanigans
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.rt_transmission = {}
---This function is calld every time a PS transmits start to end
---It should be defined by the user in the script.
---This is a table of functions. Each will be called
---@type function[]
hooks.ps_transmission = {}
-- Every function with with the s suffixed table means that other versions of that function can be in that list-table, and each one will be called
---This function is called in order to handle UDP data
---This function is called in order to handle UDP data. The string returned is sent back to the UDP peer as a response
---It should be defined by the user in the script.
---@param data string
---@return string
function data_handle(data) end
function hooks.data_handle(data) end
---This function is called when the group "L" is in the sequence
---Please remember that the core always fills in PTY and TP and PI in C if this is an B group
@@ -80,7 +102,7 @@ function data_handle(data) end
---@return integer b
---@return integer c
---@return integer d
function group(group) end
function hooks.group(group) end
---This function is called when an RDS2 group is to be generated on mode 3
---If a was returned 0, PTY and TP will be filled in, along with the PI code in C if needed
@@ -91,7 +113,7 @@ function group(group) end
---@return integer b
---@return integer c
---@return integer d
function rds2_group(stream) end
function hooks.rds2_group(stream) end
rds = {}
@@ -166,15 +188,26 @@ function rds.set_link(linkage) end
---@return boolean
function rds.get_link() end
-- String Setters (Charset converted)
-- String Setters
---@param ptyn string Program Type Name (max 8 chars)
function rds.set_ptyn(ptyn) end
---@param ptyn string Program Type Name (max 8 chars) which is expected to be already encoded in the RDS charset
function rds.set_ptyn_raw(ptyn) end
---@param ps string Program Service (8 chars)
function rds.set_ps(ps) end
---@param ps string Program Service (8 chars) which is expected to be already encoded in the RDS charset
function rds.set_ps_raw(ps) end
---@param tps string Traffic PS
function rds.set_tps(tps) end
---@param tps string Traffic PS which is expected to be already encoded in the RDS charset
function rds.set_tps_raw(tps) end
---@param rt string Radio Text (max 64 chars)
function rds.set_rt(rt) end
---@param rt string Radio Text (max 64 chars) which is expected to be already encoded in the RDS charset
function rds.set_rt_raw(rt) end
---@return nil
function rds.toggle_rt_ab() end
@@ -231,15 +264,6 @@ function rds.set_eon(eon, data) end
---@return EON_Data
function rds.get_eon(eon) end
---Sets the X/Y of the UDG
---@param xy boolean
---@param groups table Table of tables, this should be up to 8 tables containing 3 integers
function rds.set_udg(xy, groups) end
---Sets the X/Y of the UDG for RDS2
---@param xy boolean
---@param groups table Table of tables, this should be up to 8 tables containing 4 integers
function rds.set_udg2(xy, groups) end
userdata = {}
---@type integer
@@ -263,7 +287,7 @@ function userdata.get() end
---@return string
function userdata.get_offset(offset, size) end
--#endregion
--- Extensions start here - The following is made in Lua and can be used as an standard library
ext = {}
rds.ext = {}
@@ -358,4 +382,8 @@ function ext.unregister_oda_rds2(oda_id) end
---@param ert string
function rds.ext.set_ert(ert) end
---@return string
function rds.ext.get_ert() end
function rds.ext.get_ert() end
---@param designator string
---@param handler function
function rds.ext.register_group(designator, handler) end
+1 -5
View File
@@ -29,11 +29,7 @@ RDS95 is the only (as far as i can tell) encoder to transmit the 9-bit AF codes
## Lua engine
Yet another unique feature, the Lua engine allows you to parse the messages from UDP, and more!
You wanna make an ODA? Sure go for it, look in the scripts folder to see `0-ert.lua`, that is how ERT is implemmented in this encoder
Wanna do scrolling PS without C stuff and no external scripts? Just do it with the `tick` function!
Don't wanna run a bash script to send your station's data to the encoder when defaults take over? I'll welcome you to the `on_init` function
Yet another unique feature, the Lua engine allows you to control the encoder, almost entirely.
### RFT
+22
View File
@@ -0,0 +1,22 @@
hooks.registered_groups = {}
function hooks.group(group)
if hooks.registered_groups[group] then
local ok, generated, b, c, d = pcall(hooks.registered_groups[group], group)
if ok then return generated, b, c, d
else
print(generated)
return false, 0, 0, 0
end
end
return false, 0, 0, 0
end
---@param designator string
---@param handler function
function rds.ext.register_group(designator, handler)
for i = 1, #designator do
local char = designator:sub(i, i)
hooks.registered_groups[char] = handler
end
end
+1 -1
View File
@@ -51,7 +51,7 @@ function ext.set_oda_handler_rds2(oda_id, func)
_RDS2_ODAs[oda_id].handler = func
end
function rds2_group(stream)
function hooks.rds2_group(stream)
if #_RDS2_ODAs == 0 then return false, 0, 0, 0, 0 end
if _RDS2_ODA_pointer > #_RDS2_ODAs then _RDS2_ODA_pointer = 1 end
+6 -8
View File
@@ -112,16 +112,14 @@ local function get_data()
return false, 0, 0, 0
end
function group(group_type)
if group_type == "O" or group_type == "K" then
if #_RDS_ODAs == 0 then return false, 0, 0, 0 end
if _RDS_ODA_pointer > #_RDS_ODAs or _RDS_ODA_pointer < 1 then _RDS_ODA_pointer = 1 end
local function group_handler(group_type)
if #_RDS_ODAs == 0 then return false, 0, 0, 0 end
if _RDS_ODA_pointer > #_RDS_ODAs or _RDS_ODA_pointer < 1 then _RDS_ODA_pointer = 1 end
if group_type == "O" then return get_aid()
elseif group_type == "K" then return get_data() end
end
return false, 0, 0, 0
if group_type == "O" then return get_aid()
elseif group_type == "K" then return get_data() end
end
rds.ext.register_group("OK", group_handler)
table.insert(hooks.on_state, function ()
_RDS_ODAs = {}
+12 -4
View File
@@ -19,7 +19,7 @@ hooks.rt_transmission[#hooks.rt_transmission + 1] = function ()
local entry = uecp.rt_buffer[uecp.rt_buffer_index]
uecp.rt_tx_remaining = entry.number_tx
rds.set_rt(entry.text)
rds.set_rt_raw(entry.text)
if entry.toggle_ab then rds.toggle_rt_ab() end
end
@@ -167,7 +167,7 @@ mec_handlers[0x0A] = function(data)
uecp.rt_tx_remaining = number_tx
-- Seed the encoder immediately with the first entry
dsn_helper(dsn, function ()
rds.set_rt(rt_text)
rds.set_rt_raw(rt_text)
if toggle_ab then rds.toggle_rt_ab() end
rds.set_rt_enabled(true)
end)
@@ -222,7 +222,15 @@ mec_handlers[0x2E] = function (data)
end
mec_handlers[0x24] = function (data)
-- Free-format data in type A or B group
-- TODO: figure out the docs
local group = string.byte(data, 2)
local bufferdata = string.byte(data, 3)
local buffer = (bufferdata >> 5) & 3 -- No clue
local blockb = bufferdata & 31
local blockc_msb = string.byte(data, 4)
local blockc_lsb = string.byte(data, 5)
local blockd_msb = string.byte(data, 6)
local blockd_lsb = string.byte(data, 7)
rds.put_custom_group((group << 11) | blockb, (blockc_msb << 8) | blockc_lsb, (blockd_msb << 8) | blockd_lsb)
return 7
end
-- Fuck you mean, i have to implement some fucking "spinning wHELLs"? may the lord have mercy
@@ -274,7 +282,7 @@ mec_handlers[0x2D] = function (data)
local designation = string.sub(data, 3, 4)
if string.byte(designation, 1) == 0x39 and string.byte(designation, 2) == 0x35 and mel > 2 then
local data = string.sub(data, 5, 4+mel)
pcall(data_handle, data)
pcall(hooks.data_handle, data)
end
return 2+mel
end
+3 -34
View File
@@ -1,5 +1,5 @@
---@param data string
function data_handle(data)
function hooks.data_handle(data)
-- UECP
if uecp.parse_uecp and string.byte(data, 1) == 0xfe then return uecp.parse_uecp(data) end
@@ -42,7 +42,7 @@ function data_handle(data)
end
if cmd == nil then
data = data:lower()
if data == "ver" then return string.format("rds95 core v. %s - (C) 2025 radio95 - lua parser\r\n", core_version)
if data == "ver" then return string.format("rds95 core v. %s - (C) 2025 radio95 - lua parser\r\n", dp.core_version)
elseif data == "init" then
dp.set_program_defaults()
return "+\r\n"
@@ -165,37 +165,6 @@ function data_handle(data)
else return "?\r\n" end
end
local udg_num = cmd:match("^udg([12])$")
local udg2_num = cmd:match("^2udg([12])$")
if udg_num then
local xy = (udg_num == "1")
local groups = {}
for segment in value:gmatch("([^,]+)") do
local b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
if not (b and c and d) then return "-\r\n" end
table.insert(groups, {tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)})
end
if #groups > 8 or #groups == 0 then return "-\r\n" end
rds.set_udg(xy, groups)
return "+\r\n"
end
if udg2_num then
local xy = (udg2_num == "1")
local groups = {}
for segment in value:gmatch("([^,]+)") do
local a, b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
if not (a and b and c and d) then return "-" end
table.insert(groups, {tonumber(a, 16), tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)})
end
if #groups > 8 or #groups == 0 then return "-" end
rds.set_udg2(xy, groups)
return "+\r\n"
end
if cmd == "pi" then
local pi = tonumber(value, 16)
if not pi then return "-\r\n" end
@@ -264,7 +233,7 @@ function data_handle(data)
elseif cmd == "rt1" or cmd == "text" then
uecp.rt_buffer = {}
uecp.rt_buffer_index = 1
uecp.rt_buffer[1] = { text = value, number_tx = 0, toggle_ab = true }
uecp.rt_buffer[1] = { text = dp.encode_charset(value), number_tx = 0, toggle_ab = true }
uecp.rt_tx_remaining = 0
rds.set_rt_enabled(true)
rds.set_rt(value)
+240 -143
View File
@@ -76,201 +76,299 @@ uint8_t add_rds_af(RDSAFs *af_list, float freq) {
return 0;
}
char *convert_to_rdscharset(const char *str) {
static char new_str[255];
uint8_t i = 0;
void convert_to_rdscharset(const char *str, char *output, size_t buffer_size) {
size_t i = 0;
while (*str != 0 && i < 255) {
while (*str != 0 && i < buffer_size) {
// The following line is neccesary for the charset.py to work properly
// CHARSET START
switch(*str) {
case (char)0x0a: output[i] = (char)0x0a; break; // N/A
case (char)0x0d: output[i] = (char)0x0d; break; // N/A
case (char)0x1f: output[i] = (char)0x1f; break; // N/A
case (char)0x20: output[i] = (char)0x20; break; // SPACE
case (char)0x21: output[i] = (char)0x21; break; // EXCLAMATION MARK
case (char)0x22: output[i] = (char)0x22; break; // QUOTATION MARK
case (char)0x23: output[i] = (char)0x23; break; // NUMBER SIGN
case (char)0xc2:
str++;
switch(*str) {
case (char)0xa4: new_str[i] = (char)0x24; break; // CURRENCY SIGN
case (char)0xa1: new_str[i] = (char)0x8e; break; // INVERTED EXCLAMATION MARK
case (char)0xaa: new_str[i] = (char)0xa0; break; // FEMININE ORDINAL INDICATOR
case (char)0xa9: new_str[i] = (char)0xa2; break; // COPYRIGHT SIGN
case (char)0xa3: new_str[i] = (char)0xaa; break; // POUND SIGN
case (char)0xba: new_str[i] = (char)0xb0; break; // MASCULINE ORDINAL INDICATOR
case (char)0xb9: new_str[i] = (char)0xb1; break; // SUPERSCRIPT ONE
case (char)0xb1: new_str[i] = (char)0xb4; break; // PLUS-MINUS SIGN
case (char)0xb5: new_str[i] = (char)0xb8; break; // MICRO SIGN
case (char)0xbf: new_str[i] = (char)0xb9; break; // INVERTED QUESTION MARK
case (char)0xb0: new_str[i] = (char)0xbb; break; // DEGREE SIGN
case (char)0xa7: new_str[i] = (char)0xbf; break; // SECTION SIGN
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0xa4: output[i] = (char)0x24; break; // CURRENCY SIGN
case (char)0xa1: output[i] = (char)0x8e; break; // INVERTED EXCLAMATION MARK
case (char)0xaa: output[i] = (char)0xa0; break; // FEMININE ORDINAL INDICATOR
case (char)0xa9: output[i] = (char)0xa2; break; // COPYRIGHT SIGN
case (char)0xa3: output[i] = (char)0xaa; break; // POUND SIGN
case (char)0xba: output[i] = (char)0xb0; break; // MASCULINE ORDINAL INDICATOR
case (char)0xb9: output[i] = (char)0xb1; break; // SUPERSCRIPT ONE
case (char)0xb2: output[i] = (char)0xb2; break; // SUPERSCRIPT TWO
case (char)0xb3: output[i] = (char)0xb3; break; // SUPERSCRIPT THREE
case (char)0xb1: output[i] = (char)0xb4; break; // PLUS-MINUS SIGN
case (char)0xb5: output[i] = (char)0xb8; break; // MICRO SIGN
case (char)0xbf: output[i] = (char)0xb9; break; // INVERTED QUESTION MARK
case (char)0xb0: output[i] = (char)0xbb; break; // DEGREE SIGN
case (char)0xbc: output[i] = (char)0xbc; break; // VULGAR FRACTION ONE QUARTER
case (char)0xbd: output[i] = (char)0xbd; break; // VULGAR FRACTION ONE HALF
case (char)0xbe: output[i] = (char)0xbe; break; // VULGAR FRACTION THREE QUARTERS
case (char)0xa7: output[i] = (char)0xbf; break; // SECTION SIGN
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0x25: output[i] = (char)0x25; break; // PERCENT SIGN
case (char)0x26: output[i] = (char)0x26; break; // AMPERSAND
case (char)0x27: output[i] = (char)0x27; break; // APOSTROPHE
case (char)0x28: output[i] = (char)0x28; break; // LEFT PARENTHESIS
case (char)0x29: output[i] = (char)0x29; break; // RIGHT PARENTHESIS
case (char)0x2a: output[i] = (char)0x2a; break; // ASTERISK
case (char)0x2b: output[i] = (char)0x2b; break; // PLUS SIGN
case (char)0x2c: output[i] = (char)0x2c; break; // COMMA
case (char)0x2d: output[i] = (char)0x2d; break; // HYPHEN-MINUS
case (char)0x2e: output[i] = (char)0x2e; break; // FULL STOP
case (char)0x2f: output[i] = (char)0x2f; break; // SOLIDUS
case (char)0x30: output[i] = (char)0x30; break; // DIGIT ZERO
case (char)0x31: output[i] = (char)0x31; break; // DIGIT ONE
case (char)0x32: output[i] = (char)0x32; break; // DIGIT TWO
case (char)0x33: output[i] = (char)0x33; break; // DIGIT THREE
case (char)0x34: output[i] = (char)0x34; break; // DIGIT FOUR
case (char)0x35: output[i] = (char)0x35; break; // DIGIT FIVE
case (char)0x36: output[i] = (char)0x36; break; // DIGIT SIX
case (char)0x37: output[i] = (char)0x37; break; // DIGIT SEVEN
case (char)0x38: output[i] = (char)0x38; break; // DIGIT EIGHT
case (char)0x39: output[i] = (char)0x39; break; // DIGIT NINE
case (char)0x3a: output[i] = (char)0x3a; break; // COLON
case (char)0x3b: output[i] = (char)0x3b; break; // SEMICOLON
case (char)0x3c: output[i] = (char)0x3c; break; // LESS-THAN SIGN
case (char)0x3d: output[i] = (char)0x3d; break; // EQUALS SIGN
case (char)0x3e: output[i] = (char)0x3e; break; // GREATER-THAN SIGN
case (char)0x3f: output[i] = (char)0x3f; break; // QUESTION MARK
case (char)0x40: output[i] = (char)0x40; break; // COMMERCIAL AT
case (char)0x41: output[i] = (char)0x41; break; // LATIN CAPITAL LETTER A
case (char)0x42: output[i] = (char)0x42; break; // LATIN CAPITAL LETTER B
case (char)0x43: output[i] = (char)0x43; break; // LATIN CAPITAL LETTER C
case (char)0x44: output[i] = (char)0x44; break; // LATIN CAPITAL LETTER D
case (char)0x45: output[i] = (char)0x45; break; // LATIN CAPITAL LETTER E
case (char)0x46: output[i] = (char)0x46; break; // LATIN CAPITAL LETTER F
case (char)0x47: output[i] = (char)0x47; break; // LATIN CAPITAL LETTER G
case (char)0x48: output[i] = (char)0x48; break; // LATIN CAPITAL LETTER H
case (char)0x49: output[i] = (char)0x49; break; // LATIN CAPITAL LETTER I
case (char)0x4a: output[i] = (char)0x4a; break; // LATIN CAPITAL LETTER J
case (char)0x4b: output[i] = (char)0x4b; break; // LATIN CAPITAL LETTER K
case (char)0x4c: output[i] = (char)0x4c; break; // LATIN CAPITAL LETTER L
case (char)0x4d: output[i] = (char)0x4d; break; // LATIN CAPITAL LETTER M
case (char)0x4e: output[i] = (char)0x4e; break; // LATIN CAPITAL LETTER N
case (char)0x4f: output[i] = (char)0x4f; break; // LATIN CAPITAL LETTER O
case (char)0x50: output[i] = (char)0x50; break; // LATIN CAPITAL LETTER P
case (char)0x51: output[i] = (char)0x51; break; // LATIN CAPITAL LETTER Q
case (char)0x52: output[i] = (char)0x52; break; // LATIN CAPITAL LETTER R
case (char)0x53: output[i] = (char)0x53; break; // LATIN CAPITAL LETTER S
case (char)0x54: output[i] = (char)0x54; break; // LATIN CAPITAL LETTER T
case (char)0x55: output[i] = (char)0x55; break; // LATIN CAPITAL LETTER U
case (char)0x56: output[i] = (char)0x56; break; // LATIN CAPITAL LETTER V
case (char)0x57: output[i] = (char)0x57; break; // LATIN CAPITAL LETTER W
case (char)0x58: output[i] = (char)0x58; break; // LATIN CAPITAL LETTER X
case (char)0x59: output[i] = (char)0x59; break; // LATIN CAPITAL LETTER Y
case (char)0x5a: output[i] = (char)0x5a; break; // LATIN CAPITAL LETTER Z
case (char)0x5b: output[i] = (char)0x5b; break; // LEFT SQUARE BRACKET
case (char)0x5c: output[i] = (char)0x5c; break; // REVERSE SOLIDUS
case (char)0x5d: output[i] = (char)0x5d; break; // RIGHT SQUARE BRACKET
case (char)0xe2:
str++;
switch(*str) {
case (char)0x80:
str++;
switch(*str) {
case (char)0x95: new_str[i] = (char)0x5e; break; // HORIZONTAL BAR
case (char)0x96: new_str[i] = (char)0x60; break; // DOUBLE VERTICAL LINE
case (char)0xbe: new_str[i] = (char)0x7e; break; // OVERLINE
case (char)0xb0: new_str[i] = (char)0xa3; break; // PER MILLE SIGN
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0x95: output[i] = (char)0x5e; break; // HORIZONTAL BAR
case (char)0x96: output[i] = (char)0x60; break; // DOUBLE VERTICAL LINE
case (char)0xbe: output[i] = (char)0x7e; break; // OVERLINE
case (char)0xb0: output[i] = (char)0xa3; break; // PER MILLE SIGN
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0x82:
str++;
switch(*str) {
case (char)0xac: new_str[i] = (char)0xa9; break; // EURO SIGN
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0xac: output[i] = (char)0xa9; break; // EURO SIGN
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0x86:
str++;
switch(*str) {
case (char)0x90: new_str[i] = (char)0xac; break; // LEFTWARDS ARROW
case (char)0x91: new_str[i] = (char)0xad; break; // UPWARDS ARROW
case (char)0x92: new_str[i] = (char)0xae; break; // RIGHTWARDS ARROW
case (char)0x93: new_str[i] = (char)0xaf; break; // DOWNWARDS ARROW
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0x90: output[i] = (char)0xac; break; // LEFTWARDS ARROW
case (char)0x91: output[i] = (char)0xad; break; // UPWARDS ARROW
case (char)0x92: output[i] = (char)0xae; break; // RIGHTWARDS ARROW
case (char)0x93: output[i] = (char)0xaf; break; // DOWNWARDS ARROW
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0x5f: output[i] = (char)0x5f; break; // LOW LINE
case (char)0x61: output[i] = (char)0x61; break; // LATIN SMALL LETTER A
case (char)0x62: output[i] = (char)0x62; break; // LATIN SMALL LETTER B
case (char)0x63: output[i] = (char)0x63; break; // LATIN SMALL LETTER C
case (char)0x64: output[i] = (char)0x64; break; // LATIN SMALL LETTER D
case (char)0x65: output[i] = (char)0x65; break; // LATIN SMALL LETTER E
case (char)0x66: output[i] = (char)0x66; break; // LATIN SMALL LETTER F
case (char)0x67: output[i] = (char)0x67; break; // LATIN SMALL LETTER G
case (char)0x68: output[i] = (char)0x68; break; // LATIN SMALL LETTER H
case (char)0x69: output[i] = (char)0x69; break; // LATIN SMALL LETTER I
case (char)0x6a: output[i] = (char)0x6a; break; // LATIN SMALL LETTER J
case (char)0x6b: output[i] = (char)0x6b; break; // LATIN SMALL LETTER K
case (char)0x6c: output[i] = (char)0x6c; break; // LATIN SMALL LETTER L
case (char)0x6d: output[i] = (char)0x6d; break; // LATIN SMALL LETTER M
case (char)0x6e: output[i] = (char)0x6e; break; // LATIN SMALL LETTER N
case (char)0x6f: output[i] = (char)0x6f; break; // LATIN SMALL LETTER O
case (char)0x70: output[i] = (char)0x70; break; // LATIN SMALL LETTER P
case (char)0x71: output[i] = (char)0x71; break; // LATIN SMALL LETTER Q
case (char)0x72: output[i] = (char)0x72; break; // LATIN SMALL LETTER R
case (char)0x73: output[i] = (char)0x73; break; // LATIN SMALL LETTER S
case (char)0x74: output[i] = (char)0x74; break; // LATIN SMALL LETTER T
case (char)0x75: output[i] = (char)0x75; break; // LATIN SMALL LETTER U
case (char)0x76: output[i] = (char)0x76; break; // LATIN SMALL LETTER V
case (char)0x77: output[i] = (char)0x77; break; // LATIN SMALL LETTER W
case (char)0x78: output[i] = (char)0x78; break; // LATIN SMALL LETTER X
case (char)0x79: output[i] = (char)0x79; break; // LATIN SMALL LETTER Y
case (char)0x7a: output[i] = (char)0x7a; break; // LATIN SMALL LETTER Z
case (char)0x7b: output[i] = (char)0x7b; break; // LEFT CURLY BRACKET
case (char)0x7c: output[i] = (char)0x7c; break; // VERTICAL LINE
case (char)0x7d: output[i] = (char)0x7d; break; // RIGHT CURLY BRACKET
case (char)0xc3:
str++;
switch(*str) {
case (char)0xa1: new_str[i] = (char)0x80; break; // LATIN SMALL LETTER A WITH ACUTE
case (char)0xa0: new_str[i] = (char)0x81; break; // LATIN SMALL LETTER A WITH GRAVE
case (char)0xa9: new_str[i] = (char)0x82; break; // LATIN SMALL LETTER E WITH ACUTE
case (char)0xa8: new_str[i] = (char)0x83; break; // LATIN SMALL LETTER E WITH GRAVE
case (char)0xad: new_str[i] = (char)0x84; break; // LATIN SMALL LETTER I WITH ACUTE
case (char)0xac: new_str[i] = (char)0x85; break; // LATIN SMALL LETTER I WITH GRAVE
case (char)0xb3: new_str[i] = (char)0x86; break; // LATIN SMALL LETTER O WITH ACUTE
case (char)0xb2: new_str[i] = (char)0x87; break; // LATIN SMALL LETTER O WITH GRAVE
case (char)0xba: new_str[i] = (char)0x88; break; // LATIN SMALL LETTER U WITH ACUTE
case (char)0xb9: new_str[i] = (char)0x89; break; // LATIN SMALL LETTER U WITH GRAVE
case (char)0x91: new_str[i] = (char)0x8a; break; // LATIN CAPITAL LETTER N WITH TILDE
case (char)0x87: new_str[i] = (char)0x8b; break; // LATIN CAPITAL LETTER C WITH CEDILLA
case (char)0x9f: new_str[i] = (char)0x8d; break; // LATIN SMALL LETTER SHARP S
case (char)0xa2: new_str[i] = (char)0x90; break; // LATIN SMALL LETTER A WITH CIRCUMFLEX
case (char)0xa4: new_str[i] = (char)0x91; break; // LATIN SMALL LETTER A WITH DIAERESIS
case (char)0xaa: new_str[i] = (char)0x92; break; // LATIN SMALL LETTER E WITH CIRCUMFLEX
case (char)0xab: new_str[i] = (char)0x93; break; // LATIN SMALL LETTER E WITH DIAERESIS
case (char)0xae: new_str[i] = (char)0x94; break; // LATIN SMALL LETTER I WITH CIRCUMFLEX
case (char)0xaf: new_str[i] = (char)0x95; break; // LATIN SMALL LETTER I WITH DIAERESIS
case (char)0xb4: new_str[i] = (char)0x96; break; // LATIN SMALL LETTER O WITH CIRCUMFLEX
case (char)0xb6: new_str[i] = (char)0x97; break; // LATIN SMALL LETTER O WITH DIAERESIS
case (char)0xbb: new_str[i] = (char)0x98; break; // LATIN SMALL LETTER U WITH CIRCUMFLEX
case (char)0xbc: new_str[i] = (char)0x99; break; // LATIN SMALL LETTER U WITH DIAERESIS
case (char)0xb1: new_str[i] = (char)0x9a; break; // LATIN SMALL LETTER N WITH TILDE
case (char)0xa7: new_str[i] = (char)0x9b; break; // LATIN SMALL LETTER C WITH CEDILLA
case (char)0xb7: new_str[i] = (char)0xba; break; // DIVISION SIGN
case (char)0x81: new_str[i] = (char)0xc0; break; // LATIN CAPITAL LETTER A WITH ACUTE
case (char)0x80: new_str[i] = (char)0xc1; break; // LATIN CAPITAL LETTER A WITH GRAVE
case (char)0x89: new_str[i] = (char)0xc2; break; // LATIN CAPITAL LETTER E WITH ACUTE
case (char)0x88: new_str[i] = (char)0xc3; break; // LATIN CAPITAL LETTER E WITH GRAVE
case (char)0x8d: new_str[i] = (char)0xc4; break; // LATIN CAPITAL LETTER I WITH ACUTE
case (char)0x8c: new_str[i] = (char)0xc5; break; // LATIN CAPITAL LETTER I WITH GRAVE
case (char)0x93: new_str[i] = (char)0xc6; break; // LATIN CAPITAL LETTER O WITH ACUTE
case (char)0x92: new_str[i] = (char)0xc7; break; // LATIN CAPITAL LETTER O WITH GRAVE
case (char)0x9a: new_str[i] = (char)0xc8; break; // LATIN CAPITAL LETTER U WITH ACUTE
case (char)0x99: new_str[i] = (char)0xc9; break; // LATIN CAPITAL LETTER U WITH GRAVE
case (char)0x90: new_str[i] = (char)0xce; break; // LATIN CAPITAL LETTER ETH
case (char)0x82: new_str[i] = (char)0xd0; break; // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
case (char)0x84: new_str[i] = (char)0xd1; break; // LATIN CAPITAL LETTER A WITH DIAERESIS
case (char)0x8a: new_str[i] = (char)0xd2; break; // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
case (char)0x8b: new_str[i] = (char)0xd3; break; // LATIN CAPITAL LETTER E WITH DIAERESIS
case (char)0x8e: new_str[i] = (char)0xd4; break; // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
case (char)0x8f: new_str[i] = (char)0xd5; break; // LATIN CAPITAL LETTER I WITH DIAERESIS
case (char)0x94: new_str[i] = (char)0xd6; break; // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
case (char)0x96: new_str[i] = (char)0xd7; break; // LATIN CAPITAL LETTER O WITH DIAERESIS
case (char)0x9b: new_str[i] = (char)0xd8; break; // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
case (char)0x9c: new_str[i] = (char)0xd9; break; // LATIN CAPITAL LETTER U WITH DIAERESIS
case (char)0x83: new_str[i] = (char)0xe0; break; // LATIN CAPITAL LETTER A WITH TILDE
case (char)0x85: new_str[i] = (char)0xe1; break; // LATIN CAPITAL LETTER A WITH RING ABOVE
case (char)0x86: new_str[i] = (char)0xe2; break; // LATIN CAPITAL LETTER AE
case (char)0x9d: new_str[i] = (char)0xe5; break; // LATIN CAPITAL LETTER Y WITH ACUTE
case (char)0x95: new_str[i] = (char)0xe6; break; // LATIN CAPITAL LETTER O WITH TILDE
case (char)0x98: new_str[i] = (char)0xe7; break; // LATIN CAPITAL LETTER O WITH STROKE
case (char)0x9e: new_str[i] = (char)0xe8; break; // LATIN CAPITAL LETTER THORN
case (char)0xb0: new_str[i] = (char)0xef; break; // LATIN SMALL LETTER ETH
case (char)0xa3: new_str[i] = (char)0xf0; break; // LATIN SMALL LETTER A WITH TILDE
case (char)0xa5: new_str[i] = (char)0xf1; break; // LATIN SMALL LETTER A WITH RING ABOVE
case (char)0xa6: new_str[i] = (char)0xf2; break; // LATIN SMALL LETTER AE
case (char)0xbd: new_str[i] = (char)0xf5; break; // LATIN SMALL LETTER Y WITH ACUTE
case (char)0xb5: new_str[i] = (char)0xf6; break; // LATIN SMALL LETTER O WITH TILDE
case (char)0xb8: new_str[i] = (char)0xf7; break; // LATIN SMALL LETTER O WITH STROKE
case (char)0xbe: new_str[i] = (char)0xf8; break; // LATIN SMALL LETTER THORN
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0xa1: output[i] = (char)0x80; break; // LATIN SMALL LETTER A WITH ACUTE
case (char)0xa0: output[i] = (char)0x81; break; // LATIN SMALL LETTER A WITH GRAVE
case (char)0xa9: output[i] = (char)0x82; break; // LATIN SMALL LETTER E WITH ACUTE
case (char)0xa8: output[i] = (char)0x83; break; // LATIN SMALL LETTER E WITH GRAVE
case (char)0xad: output[i] = (char)0x84; break; // LATIN SMALL LETTER I WITH ACUTE
case (char)0xac: output[i] = (char)0x85; break; // LATIN SMALL LETTER I WITH GRAVE
case (char)0xb3: output[i] = (char)0x86; break; // LATIN SMALL LETTER O WITH ACUTE
case (char)0xb2: output[i] = (char)0x87; break; // LATIN SMALL LETTER O WITH GRAVE
case (char)0xba: output[i] = (char)0x88; break; // LATIN SMALL LETTER U WITH ACUTE
case (char)0xb9: output[i] = (char)0x89; break; // LATIN SMALL LETTER U WITH GRAVE
case (char)0x91: output[i] = (char)0x8a; break; // LATIN CAPITAL LETTER N WITH TILDE
case (char)0x87: output[i] = (char)0x8b; break; // LATIN CAPITAL LETTER C WITH CEDILLA
case (char)0x9f: output[i] = (char)0x8d; break; // LATIN SMALL LETTER SHARP S
case (char)0xa2: output[i] = (char)0x90; break; // LATIN SMALL LETTER A WITH CIRCUMFLEX
case (char)0xa4: output[i] = (char)0x91; break; // LATIN SMALL LETTER A WITH DIAERESIS
case (char)0xaa: output[i] = (char)0x92; break; // LATIN SMALL LETTER E WITH CIRCUMFLEX
case (char)0xab: output[i] = (char)0x93; break; // LATIN SMALL LETTER E WITH DIAERESIS
case (char)0xae: output[i] = (char)0x94; break; // LATIN SMALL LETTER I WITH CIRCUMFLEX
case (char)0xaf: output[i] = (char)0x95; break; // LATIN SMALL LETTER I WITH DIAERESIS
case (char)0xb4: output[i] = (char)0x96; break; // LATIN SMALL LETTER O WITH CIRCUMFLEX
case (char)0xb6: output[i] = (char)0x97; break; // LATIN SMALL LETTER O WITH DIAERESIS
case (char)0xbb: output[i] = (char)0x98; break; // LATIN SMALL LETTER U WITH CIRCUMFLEX
case (char)0xbc: output[i] = (char)0x99; break; // LATIN SMALL LETTER U WITH DIAERESIS
case (char)0xb1: output[i] = (char)0x9a; break; // LATIN SMALL LETTER N WITH TILDE
case (char)0xa7: output[i] = (char)0x9b; break; // LATIN SMALL LETTER C WITH CEDILLA
case (char)0xb7: output[i] = (char)0xba; break; // DIVISION SIGN
case (char)0x81: output[i] = (char)0xc0; break; // LATIN CAPITAL LETTER A WITH ACUTE
case (char)0x80: output[i] = (char)0xc1; break; // LATIN CAPITAL LETTER A WITH GRAVE
case (char)0x89: output[i] = (char)0xc2; break; // LATIN CAPITAL LETTER E WITH ACUTE
case (char)0x88: output[i] = (char)0xc3; break; // LATIN CAPITAL LETTER E WITH GRAVE
case (char)0x8d: output[i] = (char)0xc4; break; // LATIN CAPITAL LETTER I WITH ACUTE
case (char)0x8c: output[i] = (char)0xc5; break; // LATIN CAPITAL LETTER I WITH GRAVE
case (char)0x93: output[i] = (char)0xc6; break; // LATIN CAPITAL LETTER O WITH ACUTE
case (char)0x92: output[i] = (char)0xc7; break; // LATIN CAPITAL LETTER O WITH GRAVE
case (char)0x9a: output[i] = (char)0xc8; break; // LATIN CAPITAL LETTER U WITH ACUTE
case (char)0x99: output[i] = (char)0xc9; break; // LATIN CAPITAL LETTER U WITH GRAVE
case (char)0x90: output[i] = (char)0xce; break; // LATIN CAPITAL LETTER ETH
case (char)0x82: output[i] = (char)0xd0; break; // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
case (char)0x84: output[i] = (char)0xd1; break; // LATIN CAPITAL LETTER A WITH DIAERESIS
case (char)0x8a: output[i] = (char)0xd2; break; // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
case (char)0x8b: output[i] = (char)0xd3; break; // LATIN CAPITAL LETTER E WITH DIAERESIS
case (char)0x8e: output[i] = (char)0xd4; break; // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
case (char)0x8f: output[i] = (char)0xd5; break; // LATIN CAPITAL LETTER I WITH DIAERESIS
case (char)0x94: output[i] = (char)0xd6; break; // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
case (char)0x96: output[i] = (char)0xd7; break; // LATIN CAPITAL LETTER O WITH DIAERESIS
case (char)0x9b: output[i] = (char)0xd8; break; // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
case (char)0x9c: output[i] = (char)0xd9; break; // LATIN CAPITAL LETTER U WITH DIAERESIS
case (char)0x83: output[i] = (char)0xe0; break; // LATIN CAPITAL LETTER A WITH TILDE
case (char)0x85: output[i] = (char)0xe1; break; // LATIN CAPITAL LETTER A WITH RING ABOVE
case (char)0x86: output[i] = (char)0xe2; break; // LATIN CAPITAL LETTER AE
case (char)0x9d: output[i] = (char)0xe5; break; // LATIN CAPITAL LETTER Y WITH ACUTE
case (char)0x95: output[i] = (char)0xe6; break; // LATIN CAPITAL LETTER O WITH TILDE
case (char)0x98: output[i] = (char)0xe7; break; // LATIN CAPITAL LETTER O WITH STROKE
case (char)0x9e: output[i] = (char)0xe8; break; // LATIN CAPITAL LETTER THORN
case (char)0xb0: output[i] = (char)0xef; break; // LATIN SMALL LETTER ETH
case (char)0xa3: output[i] = (char)0xf0; break; // LATIN SMALL LETTER A WITH TILDE
case (char)0xa5: output[i] = (char)0xf1; break; // LATIN SMALL LETTER A WITH RING ABOVE
case (char)0xa6: output[i] = (char)0xf2; break; // LATIN SMALL LETTER AE
case (char)0xbd: output[i] = (char)0xf5; break; // LATIN SMALL LETTER Y WITH ACUTE
case (char)0xb5: output[i] = (char)0xf6; break; // LATIN SMALL LETTER O WITH TILDE
case (char)0xb8: output[i] = (char)0xf7; break; // LATIN SMALL LETTER O WITH STROKE
case (char)0xbe: output[i] = (char)0xf8; break; // LATIN SMALL LETTER THORN
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0xc5:
str++;
switch(*str) {
case (char)0x9e: new_str[i] = (char)0x8c; break; // LATIN CAPITAL LETTER S WITH CEDILLA
case (char)0x9f: new_str[i] = (char)0x9c; break; // LATIN SMALL LETTER S WITH CEDILLA
case (char)0x88: new_str[i] = (char)0xa6; break; // LATIN SMALL LETTER N WITH CARON
case (char)0x91: new_str[i] = (char)0xa7; break; // LATIN SMALL LETTER O WITH DOUBLE ACUTE
case (char)0x84: new_str[i] = (char)0xb6; break; // LATIN SMALL LETTER N WITH ACUTE
case (char)0xb1: new_str[i] = (char)0xb7; break; // LATIN SMALL LETTER U WITH DOUBLE ACUTE
case (char)0x98: new_str[i] = (char)0xca; break; // LATIN CAPITAL LETTER R WITH CARON
case (char)0xa0: new_str[i] = (char)0xcc; break; // LATIN CAPITAL LETTER S WITH CARON
case (char)0xbd: new_str[i] = (char)0xcd; break; // LATIN CAPITAL LETTER Z WITH CARON
case (char)0x99: new_str[i] = (char)0xda; break; // LATIN SMALL LETTER R WITH CARON
case (char)0xa1: new_str[i] = (char)0xdc; break; // LATIN SMALL LETTER S WITH CARON
case (char)0xbe: new_str[i] = (char)0xdd; break; // LATIN SMALL LETTER Z WITH CARON
case (char)0x80: new_str[i] = (char)0xdf; break; // LATIN SMALL LETTER L WITH MIDDLE DOT
case (char)0x92: new_str[i] = (char)0xe3; break; // LATIN CAPITAL LIGATURE OE
case (char)0xb7: new_str[i] = (char)0xe4; break; // LATIN SMALL LETTER Y WITH CIRCUMFLEX
case (char)0x8a: new_str[i] = (char)0xe9; break; // LATIN CAPITAL LETTER ENG
case (char)0x94: new_str[i] = (char)0xea; break; // LATIN CAPITAL LETTER R WITH ACUTE
case (char)0x9a: new_str[i] = (char)0xec; break; // LATIN CAPITAL LETTER S WITH ACUTE
case (char)0xb9: new_str[i] = (char)0xed; break; // LATIN CAPITAL LETTER Z WITH ACUTE
case (char)0xa6: new_str[i] = (char)0xee; break; // LATIN CAPITAL LETTER T WITH STROKE
case (char)0x93: new_str[i] = (char)0xf3; break; // LATIN SMALL LIGATURE OE
case (char)0xb5: new_str[i] = (char)0xf4; break; // LATIN SMALL LETTER W WITH CIRCUMFLEX
case (char)0x8b: new_str[i] = (char)0xf9; break; // LATIN SMALL LETTER ENG
case (char)0x95: new_str[i] = (char)0xfa; break; // LATIN SMALL LETTER R WITH ACUTE
case (char)0x9b: new_str[i] = (char)0xfc; break; // LATIN SMALL LETTER S WITH ACUTE
case (char)0xba: new_str[i] = (char)0xfd; break; // LATIN SMALL LETTER Z WITH ACUTE
case (char)0xa7: new_str[i] = (char)0xfe; break; // LATIN SMALL LETTER T WITH STROKE
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0x9e: output[i] = (char)0x8c; break; // LATIN CAPITAL LETTER S WITH CEDILLA
case (char)0x9f: output[i] = (char)0x9c; break; // LATIN SMALL LETTER S WITH CEDILLA
case (char)0x88: output[i] = (char)0xa6; break; // LATIN SMALL LETTER N WITH CARON
case (char)0x91: output[i] = (char)0xa7; break; // LATIN SMALL LETTER O WITH DOUBLE ACUTE
case (char)0x84: output[i] = (char)0xb6; break; // LATIN SMALL LETTER N WITH ACUTE
case (char)0xb1: output[i] = (char)0xb7; break; // LATIN SMALL LETTER U WITH DOUBLE ACUTE
case (char)0x98: output[i] = (char)0xca; break; // LATIN CAPITAL LETTER R WITH CARON
case (char)0xa0: output[i] = (char)0xcc; break; // LATIN CAPITAL LETTER S WITH CARON
case (char)0xbd: output[i] = (char)0xcd; break; // LATIN CAPITAL LETTER Z WITH CARON
case (char)0x99: output[i] = (char)0xda; break; // LATIN SMALL LETTER R WITH CARON
case (char)0xa1: output[i] = (char)0xdc; break; // LATIN SMALL LETTER S WITH CARON
case (char)0xbe: output[i] = (char)0xdd; break; // LATIN SMALL LETTER Z WITH CARON
case (char)0x80: output[i] = (char)0xdf; break; // LATIN SMALL LETTER L WITH MIDDLE DOT
case (char)0x92: output[i] = (char)0xe3; break; // LATIN CAPITAL LIGATURE OE
case (char)0xb7: output[i] = (char)0xe4; break; // LATIN SMALL LETTER Y WITH CIRCUMFLEX
case (char)0x8a: output[i] = (char)0xe9; break; // LATIN CAPITAL LETTER ENG
case (char)0x94: output[i] = (char)0xea; break; // LATIN CAPITAL LETTER R WITH ACUTE
case (char)0x9a: output[i] = (char)0xec; break; // LATIN CAPITAL LETTER S WITH ACUTE
case (char)0xb9: output[i] = (char)0xed; break; // LATIN CAPITAL LETTER Z WITH ACUTE
case (char)0xa6: output[i] = (char)0xee; break; // LATIN CAPITAL LETTER T WITH STROKE
case (char)0x93: output[i] = (char)0xf3; break; // LATIN SMALL LIGATURE OE
case (char)0xb5: output[i] = (char)0xf4; break; // LATIN SMALL LETTER W WITH CIRCUMFLEX
case (char)0x8b: output[i] = (char)0xf9; break; // LATIN SMALL LETTER ENG
case (char)0x95: output[i] = (char)0xfa; break; // LATIN SMALL LETTER R WITH ACUTE
case (char)0x9b: output[i] = (char)0xfc; break; // LATIN SMALL LETTER S WITH ACUTE
case (char)0xba: output[i] = (char)0xfd; break; // LATIN SMALL LETTER Z WITH ACUTE
case (char)0xa7: output[i] = (char)0xfe; break; // LATIN SMALL LETTER T WITH STROKE
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0xc4:
str++;
switch(*str) {
case (char)0xb2: new_str[i] = (char)0x8f; break; // LATIN CAPITAL LIGATURE IJ
case (char)0x9f: new_str[i] = (char)0x9d; break; // LATIN SMALL LETTER G WITH BREVE
case (char)0xb1: new_str[i] = (char)0x9e; break; // LATIN SMALL LETTER DOTLESS I
case (char)0xb3: new_str[i] = (char)0x9f; break; // LATIN SMALL LIGATURE IJ
case (char)0x9e: new_str[i] = (char)0xa4; break; // LATIN CAPITAL LETTER G WITH BREVE
case (char)0x9b: new_str[i] = (char)0xa5; break; // LATIN SMALL LETTER E WITH CARON
case (char)0xb0: new_str[i] = (char)0xb5; break; // LATIN CAPITAL LETTER I WITH DOT ABOVE
case (char)0x8c: new_str[i] = (char)0xcb; break; // LATIN CAPITAL LETTER C WITH CARON
case (char)0xbf: new_str[i] = (char)0xcf; break; // LATIN CAPITAL LETTER L WITH MIDDLE DOT
case (char)0x8d: new_str[i] = (char)0xdb; break; // LATIN SMALL LETTER C WITH CARON
case (char)0x91: new_str[i] = (char)0xde; break; // LATIN SMALL LETTER D WITH STROKE
case (char)0x86: new_str[i] = (char)0xeb; break; // LATIN CAPITAL LETTER C WITH ACUTE
case (char)0x87: new_str[i] = (char)0xfb; break; // LATIN SMALL LETTER C WITH ACUTE
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0xb2: output[i] = (char)0x8f; break; // LATIN CAPITAL LIGATURE IJ
case (char)0x9f: output[i] = (char)0x9d; break; // LATIN SMALL LETTER G WITH BREVE
case (char)0xb1: output[i] = (char)0x9e; break; // LATIN SMALL LETTER DOTLESS I
case (char)0xb3: output[i] = (char)0x9f; break; // LATIN SMALL LIGATURE IJ
case (char)0x9e: output[i] = (char)0xa4; break; // LATIN CAPITAL LETTER G WITH BREVE
case (char)0x9b: output[i] = (char)0xa5; break; // LATIN SMALL LETTER E WITH CARON
case (char)0xb0: output[i] = (char)0xb5; break; // LATIN CAPITAL LETTER I WITH DOT ABOVE
case (char)0x8c: output[i] = (char)0xcb; break; // LATIN CAPITAL LETTER C WITH CARON
case (char)0xbf: output[i] = (char)0xcf; break; // LATIN CAPITAL LETTER L WITH MIDDLE DOT
case (char)0x8d: output[i] = (char)0xdb; break; // LATIN SMALL LETTER C WITH CARON
case (char)0x91: output[i] = (char)0xde; break; // LATIN SMALL LETTER D WITH STROKE
case (char)0x86: output[i] = (char)0xeb; break; // LATIN CAPITAL LETTER C WITH ACUTE
case (char)0x87: output[i] = (char)0xfb; break; // LATIN SMALL LETTER C WITH ACUTE
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0xce:
str++;
switch(*str) {
case (char)0xb1: new_str[i] = (char)0xa1; break; // GREEK SMALL LETTER ALPHA
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0xb1: output[i] = (char)0xa1; break; // GREEK SMALL LETTER ALPHA
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0xcf:
str++;
switch(*str) {
case (char)0x80: new_str[i] = (char)0xa8; break; // GREEK SMALL LETTER PI
default: new_str[i] = (char)0x3f; break; // QUESTION MARK
case (char)0x80: output[i] = (char)0xa8; break; // GREEK SMALL LETTER PI
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
break;
case (char)0x24: new_str[i] = (char)0xab; break; // DOLLAR SIGN
default: new_str[i] = *str; break;
case (char)0x24: output[i] = (char)0xab; break; // DOLLAR SIGN
default: output[i] = (char)0x3f; break; // QUESTION MARK
}
// CHARSET END
@@ -278,6 +376,5 @@ char *convert_to_rdscharset(const char *str) {
str++;
}
new_str[i] = 0;
return new_str;
output[i] = 0;
}
+1 -1
View File
@@ -13,4 +13,4 @@ uint16_t crc16_ccitt(const char *data, uint16_t len);
uint16_t get_block_from_group(RDSGroup *group, uint8_t block);
uint8_t add_rds_af(RDSAFs *af_list, float freq);
char *convert_to_rdscharset(const char *str);
void convert_to_rdscharset(const char *str, char *output, size_t buffer_size);
+25 -79
View File
@@ -81,10 +81,12 @@ int lua_set_rds_##name(lua_State *localL) { \
enc->data[writing_program].name = luaL_checkinteger(localL, 1); \
return 0; \
}
#define STR_SETTER(name, function) \
#define STR_SETTER(name, function, buffer_size) \
int lua_set_rds_##name(lua_State *localL) { \
const char* str = luaL_checklstring(localL, 1, NULL); \
function(enc, convert_to_rdscharset(str), writing_program); \
const char* str = luaL_checklstring(localL, 1, NULL); \
char converted[buffer_size+1]; \
convert_to_rdscharset(str, converted, buffer_size+1); \
function(enc, converted, writing_program); \
return 0; \
}
#define STR_RAW_SETTER(name, function) \
@@ -244,10 +246,15 @@ int lua_put_rds2_custom_group(lua_State *localL) {
return 0;
}
STR_SETTER(ptyn, set_rds_ptyn)
STR_SETTER(ps, set_rds_ps)
STR_SETTER(tps, set_rds_tps)
STR_SETTER(rt, set_rds_rt)
STR_SETTER(ptyn, set_rds_ptyn, PTYN_LENGTH)
STR_SETTER(ps, set_rds_ps, PS_LENGTH)
STR_SETTER(tps, set_rds_tps, PS_LENGTH)
STR_SETTER(rt, set_rds_rt, RT_LENGTH)
STR_RAW_SETTER(ptyn_raw, set_rds_ptyn)
STR_RAW_SETTER(ps_raw, set_rds_ps)
STR_RAW_SETTER(tps_raw, set_rds_tps)
STR_RAW_SETTER(rt_raw, set_rds_rt)
STR_RAW_SETTER(lps, set_rds_lps)
STR_RAW_GETTER(lps, LPS_LENGTH)
@@ -374,81 +381,20 @@ int lua_get_rds_eon(lua_State *localL) {
return 1;
}
int lua_set_rds_udg(lua_State *localL) {
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
int xy = lua_toboolean(localL, 1);
luaL_checktype(localL, 2, LUA_TTABLE);
int n = lua_rawlen(localL, 2);
if(n > 8) return luaL_error(localL, "table length over 8");
uint16_t blocks[8][3] = {0};
for (int i = 1; i <= n; i++) {
lua_rawgeti(localL, 2, i);
if(lua_istable(localL, -1)) {
int n2 = lua_rawlen(localL, -1);
if(n2 > 3) return luaL_error(localL, "table length over 3");
for(int j = 1; j <= n2; j++) {
lua_rawgeti(localL, -1, j);
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
lua_pop(localL, 1);
}
}
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
lua_pop(localL, 1);
}
if(xy) {
memcpy(&(enc->data[writing_program].udg2), blocks, n * sizeof(uint16_t[3]));
enc->data[writing_program].udg2_len = n;
} else {
memcpy(&(enc->data[writing_program].udg1), blocks, n * sizeof(uint16_t[3]));
enc->data[writing_program].udg1_len = n;
}
return 0;
}
int lua_set_rds_udg2(lua_State *localL) {
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
int xy = lua_toboolean(localL, 1);
luaL_checktype(localL, 2, LUA_TTABLE);
int n = lua_rawlen(localL, 2);
if(n > 8) return luaL_error(localL, "table length over 8");
uint16_t blocks[8][4] = {0};
for (int i = 1; i <= n; i++) {
lua_rawgeti(localL, 2, i);
if(lua_istable(localL, -1)) {
int n2 = lua_rawlen(localL, -1);
if(n2 > 4) return luaL_error(localL, "table length over 4");
for(int j = 1; j <= n2; j++) {
lua_rawgeti(localL, -1, j);
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
lua_pop(localL, 1);
}
}
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
lua_pop(localL, 1);
}
if(xy) {
memcpy(&(enc->data[writing_program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
enc->data[writing_program].udg2_len_rds2 = n;
} else {
memcpy(&(enc->data[writing_program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
enc->data[writing_program].udg1_len_rds2 = n;
}
return 0;
}
int lua_crc16(lua_State *localL) {
size_t len;
const char* data = luaL_checklstring(localL, 1, &len);
lua_pushinteger(localL, crc16_ccitt(data, len));
return 1;
}
int lua_convert_to_rdscharset(lua_State *localL) {
size_t len;
const char *input = luaL_checklstring(localL, 1, &len);
char output[len + 1];
convert_to_rdscharset(input, output, len + 1);
lua_pushstring(localL, output);
return 1;
}
+7 -3
View File
@@ -72,16 +72,20 @@ int lua_set_rds_lps(lua_State *localL);
int lua_get_rds_lps(lua_State *localL);
int lua_set_rds_af_group0(lua_State *localL);
int lua_set_rds_rt(lua_State *localL);
int lua_set_rds_rt_raw(lua_State *localL);
int lua_set_rds_tps(lua_State *localL);
int lua_set_rds_tps_raw(lua_State *localL);
int lua_set_rds_ps(lua_State *localL);
int lua_set_rds_ps_raw(lua_State *localL);
int lua_set_rds_ptyn(lua_State *localL);
int lua_set_rds_ptyn_raw(lua_State *localL);
int lua_set_rds_grp_sqc(lua_State *localL);
int lua_toggle_rt_ab(lua_State *localL);
int lua_set_rds_eon(lua_State *localL);
int lua_get_rds_eon(lua_State *localL);
int lua_set_rds_udg(lua_State *localL);
int lua_set_rds_udg2(lua_State *localL);
int lua_crc16(lua_State *localL);
int lua_crc16(lua_State *localL);
int lua_convert_to_rdscharset(lua_State *localL);
+30 -22
View File
@@ -22,9 +22,6 @@ void init_lua(RDSEncoder* _enc) {
luaL_requiref(L, LUA_IOLIBNAME, luaopen_io, 1);
lua_pop(L, 6);
lua_pushstring(L, VERSION);
lua_setglobal(L, "core_version");
lua_newtable(L);
lua_setglobal(L, "ext");
@@ -53,10 +50,13 @@ void init_lua(RDSEncoder* _enc) {
lua_registertotable(L, "set_program_defaults", lua_set_rds_program_defaults);
lua_pushinteger(L, PROGRAMS);
lua_setfield(L, -2, "max_programs");
lua_pushstring(L, VERSION);
lua_setfield(L, -2, "core_version");
lua_registertotable(L, "set_output_program", lua_set_rds_program);
lua_registertotable(L, "get_output_program", lua_get_rds_program);
lua_registertotable(L, "set_writing_program", lua_set_rds_writing_program);
lua_registertotable(L, "get_writing_program", lua_get_rds_writing_program);
lua_registertotable(L, "encode_charset", lua_convert_to_rdscharset);
lua_setglobal(L, "dp");
lua_newtable(L);
@@ -69,7 +69,11 @@ void init_lua(RDSEncoder* _enc) {
lua_newtable(L);
lua_setfield(L, -2, "tick");
lua_newtable(L);
lua_setfield(L, -2, "minute_tick");
lua_newtable(L);
lua_setfield(L, -2, "rt_transmission");
lua_newtable(L);
lua_setfield(L, -2, "ps_transmission");
lua_setglobal(L, "hooks");
lua_newtable(L);
@@ -117,9 +121,13 @@ void init_lua(RDSEncoder* _enc) {
lua_registertotable(L, "get_link", lua_get_rds_link);
lua_registertotable(L, "set_ptyn", lua_set_rds_ptyn);
lua_registertotable(L, "set_ptyn_raw", lua_set_rds_ptyn_raw);
lua_registertotable(L, "set_ps", lua_set_rds_ps);
lua_registertotable(L, "set_ps_raw", lua_set_rds_ps_raw);
lua_registertotable(L, "set_tps", lua_set_rds_tps);
lua_registertotable(L, "set_tps_raw", lua_set_rds_tps_raw);
lua_registertotable(L, "set_rt", lua_set_rds_rt);
lua_registertotable(L, "set_rt_raw", lua_set_rds_rt_raw);
lua_registertotable(L, "toggle_rt_ab", lua_toggle_rt_ab);
lua_registertotable(L, "set_lps", lua_set_rds_lps);
@@ -139,9 +147,6 @@ void init_lua(RDSEncoder* _enc) {
lua_registertotable(L, "set_eon", lua_set_rds_eon);
lua_registertotable(L, "get_eon", lua_get_rds_eon);
lua_registertotable(L, "set_udg", lua_set_rds_udg);
lua_registertotable(L, "set_udg2", lua_set_rds_udg2);
lua_registertotable(L, "set_streams", lua_set_rds_streams);
lua_registertotable(L, "get_streams", lua_get_rds_streams);
@@ -166,7 +171,8 @@ void init_lua(RDSEncoder* _enc) {
void run_lua(char *str, size_t str_len, char *cmd_output, size_t *out_len) {
pthread_mutex_lock(&lua_mutex);
lua_getglobal(L, "data_handle");
lua_getglobal(L, "hooks");
lua_getfield(L, -1, "data_handle");
if (lua_isfunction(L, -1)) {
lua_pushlstring(L, str, str_len);
@@ -180,16 +186,17 @@ void run_lua(char *str, size_t str_len, char *cmd_output, size_t *out_len) {
} else fprintf(stderr, "Lua error: %s at 'data_handle'\n", lua_tostring(L, -1));
} else fprintf(stderr, "'data_handle' is not a function\n");
lua_pop(L, 1);
lua_pop(L, 2);
pthread_mutex_unlock(&lua_mutex);
}
int lua_group(RDSGroup* group, const char grp) {
pthread_mutex_lock(&lua_mutex);
lua_getglobal(L, "group");
lua_getglobal(L, "hooks");
lua_getfield(L, -1, "group");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
lua_pop(L, 2);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
@@ -198,7 +205,7 @@ int lua_group(RDSGroup* group, const char grp) {
if (lua_pcall(L, 1, 4, 0) != LUA_OK) {
fprintf(stderr, "Lua error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
lua_pop(L, 2);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
@@ -213,46 +220,47 @@ int lua_group(RDSGroup* group, const char grp) {
success = 1;
}
lua_pop(L, 4);
lua_pop(L, 5);
pthread_mutex_unlock(&lua_mutex);
return success;
}
int lua_rds2_group(RDSGroup* group, int stream) {
pthread_mutex_lock(&lua_mutex);
lua_getglobal(L, "rds2_group");
lua_getglobal(L, "hooks");
lua_getfield(L, -1, "rds2_group");
if (lua_isfunction(L, -1)) {
lua_pushinteger(L, stream);
if (lua_pcall(L, 1, 5, 0) == LUA_OK) {
if (!lua_isboolean(L, -5)) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
if (!lua_isinteger(L, -4)) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
if (!lua_isinteger(L, -3)) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
if (!lua_isinteger(L, -2)) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
if (!lua_isinteger(L, -1)) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
if(lua_toboolean(L, -5) == 0) {
lua_pop(L, 5);
lua_pop(L, 6);
pthread_mutex_unlock(&lua_mutex);
return 0;
}
@@ -261,12 +269,12 @@ int lua_rds2_group(RDSGroup* group, int stream) {
group->b = lua_tointeger(L, -3);
group->c = lua_tointeger(L, -2);
group->d = lua_tointeger(L, -1);
lua_pop(L, 5);
lua_pop(L, 6);
} else {
fprintf(stderr, "Lua error: %s at 'rds2_group'\n", lua_tostring(L, -1));
lua_pop(L, 1);
lua_pop(L, 2);
}
} else lua_pop(L, 1);
} else lua_pop(L, 2);
pthread_mutex_unlock(&lua_mutex);
return 1;
+1 -1
View File
@@ -41,7 +41,7 @@ float get_rds_sample(RDSModulator* rdsMod, uint8_t stream) {
rdsMod->data[stream].cur_bit = rdsMod->data[stream].bit_buffer[rdsMod->data[stream].bit_pos++];
rdsMod->data[stream].prev_output = rdsMod->data[stream].cur_output;
rdsMod->data[stream].cur_output = rdsMod->data[stream].prev_output ^ rdsMod->data[stream].cur_bit;
rdsMod->data[stream].cur_output = rdsMod->data[stream].prev_output ^ rdsMod->data[stream].cur_bit; // Something with differential encoding? Instead of encoding the data, encode if the bit of data changes
}
float sample = sinf(M_2PI * rdsMod->data[stream].phase + rdsMod->data[stream].symbol_shift);
+5 -50
View File
@@ -21,32 +21,7 @@ uint8_t get_rds_custom_groups(RDSEncoder* enc, RDSGroup *group);
uint8_t get_rds_custom_groups2(RDSEncoder* enc, RDSGroup *group);
int get_rdsp_lua_group(RDSGroup *group, const char grp);
#define HANDLE_UDG_STREAM(chan_idx, udg_prefix) \
do { \
if (stream != 0) { \
udg_idx = enc->state[enc->program].udg_idxs_rds2[chan_idx]; \
group->a = enc->data[enc->program].udg_prefix##_rds2[udg_idx][0]; \
group->b = enc->data[enc->program].udg_prefix##_rds2[udg_idx][1]; \
group->c = enc->data[enc->program].udg_prefix##_rds2[udg_idx][2]; \
group->d = enc->data[enc->program].udg_prefix##_rds2[udg_idx][3]; \
enc->state[enc->program].udg_idxs_rds2[chan_idx]++; \
if (enc->state[enc->program].udg_idxs_rds2[chan_idx] == enc->data[enc->program].udg_prefix##_len_rds2) \
enc->state[enc->program].udg_idxs_rds2[chan_idx] = 0; \
group->is_type_b = (group->a == 0 && IS_TYPE_B(group->b)); \
} else { \
udg_idx = enc->state[enc->program].udg_idxs[chan_idx]; \
group->b = enc->data[enc->program].udg_prefix[udg_idx][0]; \
group->c = enc->data[enc->program].udg_prefix[udg_idx][1]; \
group->d = enc->data[enc->program].udg_prefix[udg_idx][2]; \
enc->state[enc->program].udg_idxs[chan_idx]++; \
if (enc->state[enc->program].udg_idxs[chan_idx] == enc->data[enc->program].udg_prefix##_len) \
enc->state[enc->program].udg_idxs[chan_idx] = 0; \
group->is_type_b = (IS_TYPE_B(group->b) != 0); \
} \
} while(0)
static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp, uint8_t stream) {
uint8_t udg_idx;
uint8_t ps_seq_idx = (stream == 0) ? 1 : 3;
uint8_t grp_seq_idx = (stream == 0) ? 0 : 2;
switch (*grp)
@@ -73,12 +48,6 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
case 'E':
get_rds_eon_group(enc, group);
break;
case 'X':
HANDLE_UDG_STREAM(0, udg1);
break;
case 'Y':
HANDLE_UDG_STREAM(1, udg2);
break;
case 'F':
get_rds_lps_group(enc, group);
break;
@@ -92,6 +61,8 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
case 'O':
case 'K':
case 'U':
case 'X':
case 'Y':
if(get_rdsp_lua_group(group, *grp) == 0) get_rds_ps_group(enc, group);
break;
}
@@ -111,11 +82,9 @@ static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) {
}
}
}
if(*grp == 'X' && enc->data[enc->program].udg1_len != 0) good_group = 1;
if(*grp == 'Y' && enc->data[enc->program].udg2_len != 0) good_group = 1;
if(*grp == 'F' && enc->data[enc->program].lps[0] != '\0') good_group = 1;
if(*grp == 'T') good_group = 1;
if(*grp == 'L' || *grp == 'R' || *grp == 'P' || *grp == 'S' || *grp == 'O' || *grp == 'K' || *grp == 'U') good_group = 1;
if(*grp == 'L' || *grp == 'R' || *grp == 'P' || *grp == 'S' || *grp == 'O' || *grp == 'K' || *grp == 'U' || *grp == 'X' || *grp == 'Y') good_group = 1;
return good_group;
}
@@ -138,21 +107,7 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
if (utc->tm_min != enc->state[enc->program].last_minute) {
enc->state[enc->program].last_minute = utc->tm_min;
uint8_t eon_has_ta = 0;
for (int i = 0; i < EONs; i++) {
if (enc->data[enc->program].eon[i].enabled && enc->data[enc->program].eon[i].ta) {
eon_has_ta = 1;
break;
}
}
if(enc->data[enc->program].tp && enc->data[enc->program].ta && enc->state[enc->program].ta_timeout && !eon_has_ta) {
enc->state[enc->program].ta_timeout--;
if(enc->state[enc->program].ta_timeout == 0) {
enc->data[enc->program].ta = 0;
enc->state[enc->program].ta_timeout_state = enc->state[enc->program].ta_timeout;
};
}
lua_call_tfunction("minute_tick");
if(enc->data[enc->program].ct && stream == 0) {
get_rdsp_ct_group(group, now);
@@ -228,7 +183,7 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
if(!good_group) cant_find_group++;
else cant_find_group = 0;
if(!good_group && cant_find_group == 23) {
if(!good_group && cant_find_group >= 23) {
cant_find_group = 0;
break;
}
-17
View File
@@ -72,17 +72,6 @@ typedef struct {
char grp_sqc[32];
char grp_sqc_rds2[32];
uint8_t udg1_len : 4;
uint8_t udg2_len : 4;
uint8_t udg1_len_rds2 : 4;
uint8_t udg2_len_rds2 : 4;
uint16_t udg1[8][3];
uint16_t udg2[8][3];
uint16_t udg1_rds2[8][4];
uint16_t udg2_rds2[8][4];
RDSEON eon[EONs];
uint8_t lua_data[LUA_USER_DATA];
@@ -119,17 +108,12 @@ typedef struct {
uint8_t data_ecc : 1;
uint8_t grp_seq_idx[4];
uint8_t udg_idxs[2];
uint8_t udg_idxs_rds2[2];
uint8_t fasttuning_state : 3;
uint8_t last_minute : 6;
uint8_t last_second : 6;
uint8_t ta_timeout : 7;
uint8_t ta_timeout_state : 7;
uint8_t eon_index : 3;
uint8_t eon_state : 4;
RDSEONState eon_states[4];
@@ -144,7 +128,6 @@ typedef struct {
typedef struct {
uint8_t rds2_mode : 2;
// uint8_t rds2_buffer[16384];
} RDSEncoderData;
typedef struct {
RDSEncoderData encoder_data;
+6 -2
View File
@@ -61,7 +61,8 @@ void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group) {
if(enc->data[enc->program].af.num_afs) group->c = get_next_af(enc);
else {
group->b |= 1 << 11; // set to b
// Set type to B, just makes it easier for a receiver to catch the PI
group->b |= 1 << 11;
group->is_type_b = 1;
}
@@ -69,7 +70,10 @@ void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group) {
else group->d = enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2] << 8 | enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2 + 1];
enc->state[enc->program].ps_csegment++;
if (enc->state[enc->program].ps_csegment == 4) enc->state[enc->program].ps_csegment = 0;
if (enc->state[enc->program].ps_csegment == 4) {
lua_call_tfunction("ps_transmission");
enc->state[enc->program].ps_csegment = 0;
}
}
void get_rds_fasttuning_group(RDSEncoder* enc, RDSGroup *group) {