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