xref: /btstack/chipset/cc256x/convert_bts_init_scripts.py (revision f55dd2ad866d23393eff338b2945be48ef99e62a)
1d5814ca7SMatthias Ringwald#!/usr/bin/env python
2d5814ca7SMatthias Ringwald# BlueKitchen GmbH (c) 2012-2014
3d5814ca7SMatthias Ringwald
4d5814ca7SMatthias Ringwald# documentation for TI Vendor Specific commands:
5d5814ca7SMatthias Ringwald# http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands
6d5814ca7SMatthias Ringwald
7d5814ca7SMatthias Ringwaldimport glob
8d5814ca7SMatthias Ringwaldimport re
9d5814ca7SMatthias Ringwaldimport sys
10d5814ca7SMatthias Ringwaldimport os
11d5814ca7SMatthias Ringwald
12*f55dd2adSMatthias Ringwaldprint('''
13d5814ca7SMatthias RingwaldCC256x init script conversion tool for use with BTstack, v0.1
14d5814ca7SMatthias RingwaldCopyright 2012-2014 BlueKitchen GmbH
15*f55dd2adSMatthias Ringwald''')
16d5814ca7SMatthias Ringwald
17d5814ca7SMatthias Ringwaldusage = '''This script perpares init scripts for TI's
18d5814ca7SMatthias RingwaldCC256x chipsets for use with BTstack .
19d5814ca7SMatthias Ringwald
20d5814ca7SMatthias RingwaldPlease download the Service Pack for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads
21d5814ca7SMatthias RingwaldThen, unzip it and copy the *.bts file into this folder and start the script again.
22d5814ca7SMatthias Ringwald'''
23d5814ca7SMatthias Ringwald
24d5814ca7SMatthias Ringwaldfartext = '''
25d5814ca7SMatthias Ringwald#if defined(__GNUC__) && defined(__MSP430X__) && (__MSP430X__ > 0)
26d5814ca7SMatthias Ringwald__attribute__((section (".fartext")))
27d5814ca7SMatthias Ringwald#endif
28d5814ca7SMatthias Ringwald#ifdef __AVR__
29d5814ca7SMatthias Ringwald__attribute__((__progmem__))
30d5814ca7SMatthias Ringwald#endif
31d5814ca7SMatthias Ringwald'''
32d5814ca7SMatthias Ringwald
33d5814ca7SMatthias Ringwalddata_indent = '    '
34d5814ca7SMatthias Ringwald
35d5814ca7SMatthias Ringwalddef read_little_endian_16(f):
36d5814ca7SMatthias Ringwald    low  = f.read(1)
37*f55dd2adSMatthias Ringwald    if len(low) == 0:
38d5814ca7SMatthias Ringwald        return -1
39d5814ca7SMatthias Ringwald    high = f.read(1)
40d5814ca7SMatthias Ringwald    return ord(high) << 8 | ord(low)
41d5814ca7SMatthias Ringwald
42d5814ca7SMatthias Ringwalddef append_power_vector_gfsk(additions, str_list, data_indent):
43d5814ca7SMatthias Ringwald    additions.append("- added HCI_VS_SET_POWER_VECTOR(GFSK) template")
44d5814ca7SMatthias Ringwald    str_list.append(data_indent)
45d5814ca7SMatthias Ringwald    str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(GFSK) 0xFD82 template\n');
46d5814ca7SMatthias Ringwald    str_list.append(data_indent)
47d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x82, 0xfd, 0x14, 0x00, 0x9c, 0x18, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xdc,\n");
48d5814ca7SMatthias Ringwald    str_list.append(data_indent)
49d5814ca7SMatthias Ringwald    str_list.append("0xe6, 0xf0, 0xfa, 0x04, 0x0e, 0x18, 0xff, 0x00, 0x00,\n\n");
50d5814ca7SMatthias Ringwald    return 25
51d5814ca7SMatthias Ringwald
52d5814ca7SMatthias Ringwalddef append_power_vector_edr2(additions, str_list, data_indent):
53d5814ca7SMatthias Ringwald    additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR2) template")
54d5814ca7SMatthias Ringwald    str_list.append(data_indent)
55d5814ca7SMatthias Ringwald    str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(EDR2) 0xFD82 template\n');
56d5814ca7SMatthias Ringwald    str_list.append(data_indent)
57d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x82, 0xfd, 0x14, 0x01, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8, \n");
58d5814ca7SMatthias Ringwald    str_list.append(data_indent)
59d5814ca7SMatthias Ringwald    str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n");
60d5814ca7SMatthias Ringwald    return 25
61d5814ca7SMatthias Ringwald
62d5814ca7SMatthias Ringwalddef append_power_vector_edr3(additions, str_list, data_indent):
63d5814ca7SMatthias Ringwald    additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR3) template")
64d5814ca7SMatthias Ringwald    str_list.append(data_indent)
65d5814ca7SMatthias Ringwald    str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(EDR3) 0xFD82 for EDR3 template\n');
66d5814ca7SMatthias Ringwald    str_list.append(data_indent)
67d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x82, 0xfd, 0x14, 0x02, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8,\n");
68d5814ca7SMatthias Ringwald    str_list.append(data_indent)
69d5814ca7SMatthias Ringwald    str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n");
70d5814ca7SMatthias Ringwald    return 25
71d5814ca7SMatthias Ringwald
72d5814ca7SMatthias Ringwalddef append_class2_single_power(additions, str_list, data_indent):
73d5814ca7SMatthias Ringwald    additions.append("- added HCI_VS_SET_CLASS2_SINGLE_POWER template")
74d5814ca7SMatthias Ringwald    str_list.append(data_indent)
75d5814ca7SMatthias Ringwald    str_list.append('// BTstack: added HCI_VS_SET_CLASS2_SINGLE_POWER 0xFD87 template\n');
76d5814ca7SMatthias Ringwald    str_list.append(data_indent)
77d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x87, 0xfd, 0x03, 0x0d, 0x0d, 0x0d,\n\n");
78d5814ca7SMatthias Ringwald    return 7
79d5814ca7SMatthias Ringwald
80d5814ca7SMatthias Ringwalddef append_ehcill(additions, str_list, data_indent):
81d5814ca7SMatthias Ringwald    additions.append("- added eHCILL template")
82d5814ca7SMatthias Ringwald    str_list.append('\n')
83d5814ca7SMatthias Ringwald    str_list.append(data_indent)
84d5814ca7SMatthias Ringwald    str_list.append('// BTstack: added HCI_VS_Sleep_Mode_Configurations 0xFD0C template for eHCILL\n');
85d5814ca7SMatthias Ringwald    str_list.append(data_indent)
86d5814ca7SMatthias Ringwald    str_list.append('0x01, 0x0c, 0xfd, 9 , 1, 0, 0,  0xff, 0xff, 0xff, 0xff, 100, 0,\n\n');
87d5814ca7SMatthias Ringwald    return 13
88d5814ca7SMatthias Ringwald
89d5814ca7SMatthias Ringwalddef append_calibration_sequence(additions, str_list, data_indent):
90d5814ca7SMatthias Ringwald    additions.append("- added calibration sequence")
91d5814ca7SMatthias Ringwald    str_list.append(data_indent)
92d5814ca7SMatthias Ringwald    str_list.append("// BTstack: added calibration sequence\n")
93d5814ca7SMatthias Ringwald    str_list.append(data_indent)
94d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x80, 0xfd, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,\n")
95d5814ca7SMatthias Ringwald    str_list.append(data_indent)
96d5814ca7SMatthias Ringwald    str_list.append("0x01, 0x80, 0xfd, 0x06, 0x3c, 0xf0, 0x5f, 0x00, 0x00, 0x00,\n\n")
97d5814ca7SMatthias Ringwald    return 20
98d5814ca7SMatthias Ringwald
99d5814ca7SMatthias Ringwalddef convert_bts(main_bts_file, bts_add_on):
100d5814ca7SMatthias Ringwald    array_name = 'cc256x'
101d5814ca7SMatthias Ringwald    c_file   = main_bts_file.replace('bts', 'c')
102d5814ca7SMatthias Ringwald
103d5814ca7SMatthias Ringwald    input_files = [ main_bts_file ]
104d5814ca7SMatthias Ringwald    if bts_add_on != "":
105d5814ca7SMatthias Ringwald        input_files.append(bts_add_on)
106d5814ca7SMatthias Ringwald
107d5814ca7SMatthias Ringwald    with open(c_file, 'w') as fout:
108d5814ca7SMatthias Ringwald
109d5814ca7SMatthias Ringwald        # assert script contains templates for configuration by BTstack
110d5814ca7SMatthias Ringwald        have_eHCILL = False
111d5814ca7SMatthias Ringwald        have_power_vector_gfsk = False;
112d5814ca7SMatthias Ringwald        have_power_vector_edr2 = False;
113d5814ca7SMatthias Ringwald        have_power_vector_edr3 = False;
114d5814ca7SMatthias Ringwald        have_class2_single_power = False;
115d5814ca7SMatthias Ringwald
116*f55dd2adSMatthias Ringwald        print("Creating {0}".format(c_file))
117d5814ca7SMatthias Ringwald
118d5814ca7SMatthias Ringwald        part_size = 0
119d5814ca7SMatthias Ringwald
120d5814ca7SMatthias Ringwald        parts = 0
121d5814ca7SMatthias Ringwald        str_list = []
122d5814ca7SMatthias Ringwald        part_strings = []
123d5814ca7SMatthias Ringwald        part_sizes   = []
124d5814ca7SMatthias Ringwald        additions = []
125d5814ca7SMatthias Ringwald
126d5814ca7SMatthias Ringwald        for bts_file in input_files:
127d5814ca7SMatthias Ringwald
128d5814ca7SMatthias Ringwald            with open (bts_file, 'rb') as fin:
129d5814ca7SMatthias Ringwald
130*f55dd2adSMatthias Ringwald                print("- parsing {0:32}".format(bts_file))
131d5814ca7SMatthias Ringwald
132d5814ca7SMatthias Ringwald                header = fin.read(32)
133*f55dd2adSMatthias Ringwald                if header[0:4].decode('ascii') != 'BTSB':
134*f55dd2adSMatthias Ringwald                    print('Error', bts_file, 'is not a valid .BTS file')
135d5814ca7SMatthias Ringwald                    sys.exit(1)
136d5814ca7SMatthias Ringwald
137d5814ca7SMatthias Ringwald
138d5814ca7SMatthias Ringwald                while True:
139d5814ca7SMatthias Ringwald                    action_type = read_little_endian_16(fin)
140d5814ca7SMatthias Ringwald                    action_size = read_little_endian_16(fin)
141*f55dd2adSMatthias Ringwald                    action_data = bytearray(fin.read(action_size))
142d5814ca7SMatthias Ringwald
143d5814ca7SMatthias Ringwald                    if (action_type == 1):  # hci command
144d5814ca7SMatthias Ringwald
145*f55dd2adSMatthias Ringwald                        # opcode = (ord(action_data[2]) << 8) | ord(action_data[1])
146*f55dd2adSMatthias Ringwald                        opcode = (action_data[2] << 8) | action_data[1]
147d5814ca7SMatthias Ringwald                        if opcode == 0xFF36:
148d5814ca7SMatthias Ringwald                            continue    # skip baud rate command
149d5814ca7SMatthias Ringwald                        if opcode == 0xFD0C:
150d5814ca7SMatthias Ringwald                            have_eHCILL = True
151d5814ca7SMatthias Ringwald                        if opcode == 0xFD82:
152d5814ca7SMatthias Ringwald                            modulation_type = ord(action_data[4])
153d5814ca7SMatthias Ringwald                            if modulation_type == 0:
154d5814ca7SMatthias Ringwald                                have_power_vector_gfsk = True
155d5814ca7SMatthias Ringwald                            elif modulation_type == 1:
156d5814ca7SMatthias Ringwald                                have_power_vector_edr2 + True
157d5814ca7SMatthias Ringwald                            elif modulation_type == 2:
158d5814ca7SMatthias Ringwald                                have_power_vector_edr3 = True
159d5814ca7SMatthias Ringwald                        if opcode == 0xFD80:
160d5814ca7SMatthias Ringwald                            # add missing power command templates
161d5814ca7SMatthias Ringwald                            if not have_power_vector_gfsk:
162d5814ca7SMatthias Ringwald                                part_size += append_power_vector_gfsk(additions, str_list, data_indent)
163d5814ca7SMatthias Ringwald                                have_power_vector_gfsk = True;
164d5814ca7SMatthias Ringwald                            if not have_power_vector_edr2:
165d5814ca7SMatthias Ringwald                                part_size += append_power_vector_edr2(additions, str_list, data_indent)
166d5814ca7SMatthias Ringwald                                have_power_vector_edr2 = True;
167d5814ca7SMatthias Ringwald                            if not have_power_vector_edr3:
168d5814ca7SMatthias Ringwald                                part_size += append_power_vector_edr2(additions, str_list, data_indent)
169d5814ca7SMatthias Ringwald                                have_power_vector_edr3 = True;
170d5814ca7SMatthias Ringwald                            if not have_class2_single_power:
171d5814ca7SMatthias Ringwald                                part_size += append_class2_single_power(additions, str_list, data_indent)
172d5814ca7SMatthias Ringwald                                have_class2_single_power = True;
173d5814ca7SMatthias Ringwald
174d5814ca7SMatthias Ringwald                        counter = 0
175d5814ca7SMatthias Ringwald                        str_list.append(data_indent)
176d5814ca7SMatthias Ringwald                        for byte in action_data:
177*f55dd2adSMatthias Ringwald                            str_list.append("0x{0:02x}, ".format(byte))
178d5814ca7SMatthias Ringwald                            counter = counter + 1
179d5814ca7SMatthias Ringwald                            if (counter != 15):
180d5814ca7SMatthias Ringwald                                continue
181d5814ca7SMatthias Ringwald                            counter = 0
182d5814ca7SMatthias Ringwald                            str_list.append("\n")
183d5814ca7SMatthias Ringwald                            str_list.append(data_indent)
184d5814ca7SMatthias Ringwald                        str_list.append("\n\n")
185d5814ca7SMatthias Ringwald
186d5814ca7SMatthias Ringwald                        part_size = part_size + action_size
187d5814ca7SMatthias Ringwald
188d5814ca7SMatthias Ringwald                        # 30 kB chunks
189d5814ca7SMatthias Ringwald                        if part_size < 30 * 1024:
190d5814ca7SMatthias Ringwald                            continue
191d5814ca7SMatthias Ringwald
192d5814ca7SMatthias Ringwald                        part_strings.append(''.join(str_list))
193d5814ca7SMatthias Ringwald                        part_sizes.append(part_size)
194d5814ca7SMatthias Ringwald                        parts += 1
195d5814ca7SMatthias Ringwald
196d5814ca7SMatthias Ringwald                        str_list = []
197d5814ca7SMatthias Ringwald                        part_size = 0
198d5814ca7SMatthias Ringwald
199d5814ca7SMatthias Ringwald                    if (action_type == 6):  # comment
200*f55dd2adSMatthias Ringwald                        action_data = action_data.decode('ascii').rstrip('\0')
201d5814ca7SMatthias Ringwald                        str_list.append(data_indent)
202d5814ca7SMatthias Ringwald                        str_list.append("// " + action_data + "\n")
203d5814ca7SMatthias Ringwald
204d5814ca7SMatthias Ringwald                    if (action_type < 0):   # EOF
205d5814ca7SMatthias Ringwald                        break;
206d5814ca7SMatthias Ringwald
207d5814ca7SMatthias Ringwald
208d5814ca7SMatthias Ringwald        if not have_eHCILL:
209d5814ca7SMatthias Ringwald            part_size += append_ehcill(additions, str_list, data_indent)
210d5814ca7SMatthias Ringwald
211d5814ca7SMatthias Ringwald        # append calibration step, if missing so far
212d5814ca7SMatthias Ringwald        all_power_commands_provided = have_power_vector_gfsk and have_power_vector_edr2 and have_power_vector_edr3 and have_class2_single_power
213d5814ca7SMatthias Ringwald        if not all_power_commands_provided:
214d5814ca7SMatthias Ringwald            str_list.append("\n" + data_indent + "// BTstack: no calibration sequence found, adding power commands and calibration\n\n")
215d5814ca7SMatthias Ringwald            part_size += append_power_vector_gfsk(additions, str_list, data_indent)
216d5814ca7SMatthias Ringwald            part_size += append_power_vector_edr2(additions, str_list, data_indent)
217d5814ca7SMatthias Ringwald            part_size += append_power_vector_edr2(additions, str_list, data_indent)
218d5814ca7SMatthias Ringwald            part_size += append_class2_single_power(additions, str_list, data_indent)
219d5814ca7SMatthias Ringwald            part_size += append_calibration_sequence(additions, str_list, data_indent)
220d5814ca7SMatthias Ringwald
221d5814ca7SMatthias Ringwald        part_strings.append(''.join(str_list))
222d5814ca7SMatthias Ringwald        part_sizes.append(part_size)
223d5814ca7SMatthias Ringwald        parts += 1
224d5814ca7SMatthias Ringwald
225d5814ca7SMatthias Ringwald        fout.write( '// init script created from\n')
226d5814ca7SMatthias Ringwald        fout.write( '// - {0}\n'.format(main_bts_file))
227d5814ca7SMatthias Ringwald        if bts_add_on != "":
228d5814ca7SMatthias Ringwald            fout.write( '// - {0}\n'.format(bts_add_on))
229d5814ca7SMatthias Ringwald        fout.write( '#include <stdint.h>\n')
230d5814ca7SMatthias Ringwald
231d5814ca7SMatthias Ringwald        part = 0
232d5814ca7SMatthias Ringwald        size = 0
233d5814ca7SMatthias Ringwald        for part_size in part_sizes:
234d5814ca7SMatthias Ringwald            part += 1
235d5814ca7SMatthias Ringwald            size += part_size
236*f55dd2adSMatthias Ringwald            print("- part", part, "size", part_size)
237d5814ca7SMatthias Ringwald
238*f55dd2adSMatthias Ringwald        print('- total size', size)
239d5814ca7SMatthias Ringwald
240*f55dd2adSMatthias Ringwald        print("\n".join(additions))
241d5814ca7SMatthias Ringwald
242d5814ca7SMatthias Ringwald
243d5814ca7SMatthias Ringwald        part = 0
244d5814ca7SMatthias Ringwald        for part_text in part_strings:
245d5814ca7SMatthias Ringwald            part += 1
246d5814ca7SMatthias Ringwald            suffix = ''
247d5814ca7SMatthias Ringwald
248d5814ca7SMatthias Ringwald            if part == 1:
249d5814ca7SMatthias Ringwald                fout.write( fartext )
250d5814ca7SMatthias Ringwald
251d5814ca7SMatthias Ringwald            if (part > 1):
252d5814ca7SMatthias Ringwald                suffix = '_{0}'.format(part)
253d5814ca7SMatthias Ringwald                fout.write('#if defined(__GNUC__) && defined(__GNUC__) && (__MSP430X__ > 0)\n')
254d5814ca7SMatthias Ringwald                fout.write('};\n')
255d5814ca7SMatthias Ringwald                fout.write('__attribute__((section (".fartext")))\n')
256d5814ca7SMatthias Ringwald
257d5814ca7SMatthias Ringwald            fout.write('const uint8_t {0}_init_script{1}[] = {2}\n\n'.format(array_name, suffix, '{'))
258d5814ca7SMatthias Ringwald
259d5814ca7SMatthias Ringwald            if (part > 1):
260d5814ca7SMatthias Ringwald                fout.write('#endif\n')
261d5814ca7SMatthias Ringwald
262d5814ca7SMatthias Ringwald            fout.write(part_text)
263d5814ca7SMatthias Ringwald
264d5814ca7SMatthias Ringwald
265d5814ca7SMatthias Ringwald        fout.write('};\n\n')
266d5814ca7SMatthias Ringwald
267d5814ca7SMatthias Ringwald        fout.write('const uint32_t {0}_init_script_size = {1};\n\n'.format(array_name,size));
268d5814ca7SMatthias Ringwald        # fout.write('void main() {0} printf("size {1}\\n", {2}_init_script_size); {3}'.format('{', '%u', array_name,'}'));
269d5814ca7SMatthias Ringwald
270d5814ca7SMatthias Ringwald# get list of *.bts files
271d5814ca7SMatthias Ringwaldfiles =  glob.glob('*.bts')
272d5814ca7SMatthias Ringwaldif not files:
273*f55dd2adSMatthias Ringwald    print(usage)
274d5814ca7SMatthias Ringwald    sys.exit(1)
275d5814ca7SMatthias Ringwald
276d5814ca7SMatthias Ringwald# convert each of them
277d5814ca7SMatthias Ringwaldfor name in files:
278d5814ca7SMatthias Ringwald    name_lower = name.lower()
279d5814ca7SMatthias Ringwald    # skip BLE and AVRP add-ons
280d5814ca7SMatthias Ringwald    if name_lower.startswith('ble_init_cc'):
281*f55dd2adSMatthias Ringwald        print("Skipping BLE add-on", name)
282d5814ca7SMatthias Ringwald        continue
283d5814ca7SMatthias Ringwald    if name_lower.startswith('avpr_init_cc'):
284*f55dd2adSMatthias Ringwald        print("Skipping AVPR add-on", name)
285d5814ca7SMatthias Ringwald        continue
286d5814ca7SMatthias Ringwald    if re.match("initscripts_tiinit_.*_ble_add-on.bts", name_lower):
287*f55dd2adSMatthias Ringwald        print("Skipping BLE add-on", name)
288d5814ca7SMatthias Ringwald        continue
289d5814ca7SMatthias Ringwald    if re.match("initscripts_tiinit_.*_avpr_add-on.bts", name_lower):
290*f55dd2adSMatthias Ringwald        print("Skipping AVPR add-on", name)
291*f55dd2adSMatthias Ringwald        continue
292d5814ca7SMatthias Ringwald
293d5814ca7SMatthias Ringwald    # check for BLE add-on
294d5814ca7SMatthias Ringwald    add_on = ""
295d5814ca7SMatthias Ringwald    name_parts = re.match('bluetooth_init_(.....+_...)_.*.bts', name)
296d5814ca7SMatthias Ringwald    if name_parts:
297d5814ca7SMatthias Ringwald        potential_add_on = 'BLE_init_%s.bts' % name_parts.group(1)
298d5814ca7SMatthias Ringwald        if os.path.isfile(potential_add_on):
299d5814ca7SMatthias Ringwald            add_on = potential_add_on
300*f55dd2adSMatthias Ringwald            print("Found", add_on, "add-on for", name)
301d5814ca7SMatthias Ringwald
302d5814ca7SMatthias Ringwald    name_parts = re.match('initscripts_TIInit_(\d*\.\d*\.\d*)_.*.bts', name)
303d5814ca7SMatthias Ringwald    if name_parts:
304d5814ca7SMatthias Ringwald        potential_add_on = 'initscripts_TIInit_%s_ble_add-on.bts' % name_parts.group(1)
305d5814ca7SMatthias Ringwald        if os.path.isfile(potential_add_on):
306d5814ca7SMatthias Ringwald            add_on = potential_add_on
307*f55dd2adSMatthias Ringwald            print("Found", add_on, "add-on for", name)
308d5814ca7SMatthias Ringwald
309d5814ca7SMatthias Ringwald    convert_bts(name, add_on)
310d5814ca7SMatthias Ringwald
311d5814ca7SMatthias Ringwald# done
312*f55dd2adSMatthias Ringwaldprint('\nConversion(s) successful!\n')
313d5814ca7SMatthias Ringwald
314d5814ca7SMatthias Ringwald
315d5814ca7SMatthias Ringwald
316