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 12f55dd2adSMatthias Ringwaldprint(''' 13d5814ca7SMatthias RingwaldCC256x init script conversion tool for use with BTstack, v0.1 14d5814ca7SMatthias RingwaldCopyright 2012-2014 BlueKitchen GmbH 15f55dd2adSMatthias Ringwald''') 16d5814ca7SMatthias Ringwald 17*c4054521SMatthias Ringwaldusage = '''This script prepares 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) 37f55dd2adSMatthias 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"); 50*c4054521SMatthias Ringwald return 24 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"); 60*c4054521SMatthias Ringwald return 24 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"); 70*c4054521SMatthias Ringwald return 24 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 116f55dd2adSMatthias 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 130f55dd2adSMatthias Ringwald print("- parsing {0:32}".format(bts_file)) 131d5814ca7SMatthias Ringwald 132d5814ca7SMatthias Ringwald header = fin.read(32) 133f55dd2adSMatthias Ringwald if header[0:4].decode('ascii') != 'BTSB': 134f55dd2adSMatthias 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) 141f55dd2adSMatthias Ringwald action_data = bytearray(fin.read(action_size)) 142d5814ca7SMatthias Ringwald 143d5814ca7SMatthias Ringwald if (action_type == 1): # hci command 144d5814ca7SMatthias Ringwald 145f55dd2adSMatthias Ringwald # opcode = (ord(action_data[2]) << 8) | ord(action_data[1]) 146f55dd2adSMatthias 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: 177f55dd2adSMatthias 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 200f55dd2adSMatthias 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 236f55dd2adSMatthias Ringwald print("- part", part, "size", part_size) 237d5814ca7SMatthias Ringwald 238f55dd2adSMatthias Ringwald print('- total size', size) 239d5814ca7SMatthias Ringwald 240f55dd2adSMatthias 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: 273f55dd2adSMatthias 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'): 281f55dd2adSMatthias Ringwald print("Skipping BLE add-on", name) 282d5814ca7SMatthias Ringwald continue 283d5814ca7SMatthias Ringwald if name_lower.startswith('avpr_init_cc'): 284f55dd2adSMatthias Ringwald print("Skipping AVPR add-on", name) 285d5814ca7SMatthias Ringwald continue 286d5814ca7SMatthias Ringwald if re.match("initscripts_tiinit_.*_ble_add-on.bts", name_lower): 287f55dd2adSMatthias Ringwald print("Skipping BLE add-on", name) 288d5814ca7SMatthias Ringwald continue 289d5814ca7SMatthias Ringwald if re.match("initscripts_tiinit_.*_avpr_add-on.bts", name_lower): 290f55dd2adSMatthias Ringwald print("Skipping AVPR add-on", name) 291f55dd2adSMatthias 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 300f55dd2adSMatthias 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 307f55dd2adSMatthias Ringwald print("Found", add_on, "add-on for", name) 308d5814ca7SMatthias Ringwald 309d5814ca7SMatthias Ringwald convert_bts(name, add_on) 310d5814ca7SMatthias Ringwald 311d5814ca7SMatthias Ringwald# done 312f55dd2adSMatthias Ringwaldprint('\nConversion(s) successful!\n') 313d5814ca7SMatthias Ringwald 314d5814ca7SMatthias Ringwald 315d5814ca7SMatthias Ringwald 316