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