diff --git a/chipset-cc256x/bt_control_cc256x.c b/chipset-cc256x/bt_control_cc256x.c new file mode 100644 index 000000000..ebb37aba9 --- /dev/null +++ b/chipset-cc256x/bt_control_cc256x.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * bt_control_cc256x.c + * + * Adapter to use cc256x-based chipsets with BTstack + * + * Handles init script (a.k.a. Service Patch) + * Allows for non-standard UART baud rate + * Allows to configure transmit power + * Allows to activate eHCILL deep sleep mode + * + * Issues with mspgcc LTS: + * - 20 bit support is not there yet -> .text cannot get bigger than 48 kb + * - arrays cannot have more than 32k entries + * + * workarounds: + * - store init script in .fartext and use assembly code to read from there + * - split into two arrays + * + */ + +#include "bt_control_cc256x.h" + +#include /* NULL */ +#include +#include /* memcpy */ + +#if defined(__GNUC__) && (__MSP430X__ > 0) +#include "hal_compat.h" +#endif + +#include "bt_control.h" + + +// actual init script provided by seperate .c file +extern const uint8_t cc256x_init_script[]; +extern const uint32_t cc256x_init_script_size; + +// +static uint32_t init_script_offset = 0; +static int16_t init_power_in_dB = 13; // 13 dBm +static int init_ehcill_enabled = 0; + + +static int bt_control_cc256x_on(void *config){ + init_script_offset = 0; + return 0; +} + +// UART Baud Rate control from: http://e2e.ti.com/support/low_power_rf/f/660/p/134850/484763.aspx +static int cc256x_baudrate_cmd(void * config, uint32_t baudrate, uint8_t *hci_cmd_buffer){ + hci_cmd_buffer[0] = 0x36; + hci_cmd_buffer[1] = 0xFF; + hci_cmd_buffer[2] = 0x04; + hci_cmd_buffer[3] = baudrate & 0xff; + hci_cmd_buffer[4] = (baudrate >> 8) & 0xff; + hci_cmd_buffer[5] = (baudrate >> 16) & 0xff; + hci_cmd_buffer[6] = 0; + return 0; +} + + +// Output Power control from: http://e2e.ti.com/support/low_power_rf/f/660/p/134853/484767.aspx +#define NUM_POWER_LEVELS 16 +#define DB_MIN_LEVEL -35 +#define DB_PER_LEVEL 5 +#define DB_DYNAMIC_RANGE 30 + +static int get_max_power_for_modulation_type(int type){ + // a) limit max output power + int power_db; + switch (type){ + case 0: // GFSK + power_db = 12; + break; + default: // EDRx + power_db = 10; + break; + } + if (power_db > init_power_in_dB) { + power_db = init_power_in_dB; + } + return power_db; +} + +static int get_highest_level_for_given_power(int power_db, int recommended_db){ + int i = NUM_POWER_LEVELS-1; + while (i) { + if (power_db < recommended_db) { + return i; + } + power_db -= DB_PER_LEVEL; + i--; + } + return 0; +} + +static void update_set_power_vector(uint8_t *hci_cmd_buffer){ + int i; + int power_db = get_max_power_for_modulation_type(hci_cmd_buffer[3]); + int dynamic_range = 0; + // f) don't touch level 0 + for ( i = (NUM_POWER_LEVELS-1) ; i >= 1 ; i--){ + hci_cmd_buffer[4+i] = 2 * power_db; + + if (dynamic_range + DB_PER_LEVEL > DB_DYNAMIC_RANGE) continue; // e) + + power_db -= DB_PER_LEVEL; // d) + dynamic_range += DB_PER_LEVEL; + + if (power_db > DB_MIN_LEVEL) continue; + + power_db = DB_MIN_LEVEL; // b) + } +} + +static void update_set_class2_single_power(uint8_t * hci_cmd_buffer){ + int i = 0; + for (i=0;i<3;i++){ + hci_cmd_buffer[3+i] = get_highest_level_for_given_power(get_max_power_for_modulation_type(i), 4); + } +} + +// eHCILL activate from http://e2e.ti.com/support/low_power_rf/f/660/p/134855/484776.aspx +static void update_sleep_mode_configurations(uint8_t * hci_cmd_buffer){ + if (init_ehcill_enabled) { + hci_cmd_buffer[4] = 1; + } else { + hci_cmd_buffer[4] = 0; + } +} + +static void bt_control_cc256x_update_command(uint8_t *hci_cmd_buffer){ + + uint16_t opcode = hci_cmd_buffer[0] | (hci_cmd_buffer[1] << 8); + + switch (opcode){ + case 0xFD87: + update_set_class2_single_power(hci_cmd_buffer); + break; + case 0xFD82: + update_set_power_vector(hci_cmd_buffer); + break; + case 0xFD0C: + update_sleep_mode_configurations(hci_cmd_buffer); + break; + default: + break; + } +} + +static int bt_control_cc256x_next_cmd(void *config, uint8_t *hci_cmd_buffer){ + + if (init_script_offset >= cc256x_init_script_size) { + return 0; + } + + init_script_offset++; // extracted init script has 0x01 cmd packet type, but BTstack expects them without + +#if defined(__GNUC__) && (__MSP430X__ > 0) + + // workaround: use FlashReadBlock with 32-bit integer and assume init script starts at 0x10000 + uint32_t init_script_addr = 0x10000; + FlashReadBlock(&hci_cmd_buffer[0], init_script_addr + init_script_offset, 3); // cmd header + init_script_offset += 3; + int payload_len = hci_cmd_buffer[2]; + FlashReadBlock(&hci_cmd_buffer[3], init_script_addr + init_script_offset, payload_len); // cmd payload + +#else + + // use memcpy with pointer + uint8_t * init_script_ptr = (uint8_t*) &cc256x_init_script[0]; + memcpy(&hci_cmd_buffer[0], init_script_ptr + init_script_offset, 3); // cmd header + init_script_offset += 3; + int payload_len = hci_cmd_buffer[2]; + memcpy(&hci_cmd_buffer[3], init_script_ptr + init_script_offset, payload_len); // cmd payload + +#endif + + // support for cc256x power commands and ehcill + bt_control_cc256x_update_command(hci_cmd_buffer); + + init_script_offset += payload_len; + + return 1; +} + +// MARK: const structs + +static const bt_control_t bt_control_cc256x = { + .on = bt_control_cc256x_on, + .next_cmd = bt_control_cc256x_next_cmd, + .baudrate_cmd = cc256x_baudrate_cmd +}; + +static const hci_uart_config_t hci_uart_config_cc256x = { + .baudrate_init = 57600, + .baudrate_main = 1000000 +}; + +// MARK: public API + +void bt_control_cc256x_enable_ehcill(int on){ + init_ehcill_enabled = on; +} + +int bt_control_cc256x_ehcill_enabled(void){ + return init_ehcill_enabled; +} +void bt_control_cc256x_set_power(int16_t power_in_dB){ + init_power_in_dB = power_in_dB; +} + +bt_control_t *bt_control_cc256x_instance(void){ + return (bt_control_t*) &bt_control_cc256x; +} + +hci_uart_config_t *hci_uart_config_cc256x_instance(void){ + return (hci_uart_config_t*) &hci_uart_config_cc256x; +} diff --git a/chipset-cc256x/bt_control_cc256x.h b/chipset-cc256x/bt_control_cc256x.h new file mode 100644 index 000000000..65778df25 --- /dev/null +++ b/chipset-cc256x/bt_control_cc256x.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * bt_control_cc256x.c + * + * Adapter to use cc256x-based chipsets with BTstack + */ + +#pragma once + +#include +#include "bt_control.h" +#include "hci_transport.h" + +bt_control_t *bt_control_cc256x_instance(void); +void bt_control_cc256x_set_power(int16_t power_in_dB); + +void bt_control_cc256x_enable_ehcill(int on); +int bt_control_cc256x_ehcill_enabled(void); + +hci_uart_config_t *hci_uart_config_cc256x_instance(void); \ No newline at end of file diff --git a/chipset-cc256x/create_cc256x_init_scipts.py b/chipset-cc256x/create_cc256x_init_scipts.py new file mode 100755 index 000000000..26cd5df7f --- /dev/null +++ b/chipset-cc256x/create_cc256x_init_scipts.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# + +usage = '''This script extracts the init scripts needed to use TI's +CC2560/CC2567 with BTstack from the Stellaris Bluetopia SDK. + +Please download and install the Bluetopia SDK available at +http://www.ti.com/tool/sw-dk-em2-2560b on a Windows system +and copy 'Stellarware/Bluetopia/btpsvend/BTPSVEND.c' +into the current directory. Then start the script again. +''' + +import re +import sys + +print ''' +CC256x init script extraction for use with BTstack, v0.1 +Copyright 2011 Matthias Ringwald +''' + +def extract_script(fin, patch_name, chipset, array_name): + + fartext = ''' +#if defined(__GNUC__) && (__MSP430X__ > 0) +__attribute__((section (".fartext"))) +#endif +''' + + filename = '{0}_init_script.c'.format(chipset) + + fout = open (filename,'w') + + fout.write( '// init script for {0} extracted from Stellaris Bluetopia SDK\n'.format(chipset)) + fout.write( '#include \n') + fout.write( fartext ) + fout.write( 'const uint8_t {1}_init_script[] =\n'.format(chipset,array_name)) + + in_script = False + second_part = False + size = 0 + + for line in f: + line = line.strip("\n\r ") + if not in_script: + if line.find('{0}[]'.format(patch_name)) >= 0: + in_script = True + else: + + if line.find('};') >= 0 or line.find('} ;') >= 0: + fout.write('// BTstack: add HCI_VS_Sleep_Mode_Configurations 0xFD0C template for eHCILL\n'); + fout.write('0x01, 0x0c, 0xfd, 9 , 1, 0, 0, 0xff, 0xff, 0xff, 0xff, 100, 0\n'); + fout.write('};\n') + break; + + if not second_part: + size = size + 16 + if size > 20*1024: + fout.write ('};\n') + fout.write (fartext) + fout.write ('const uint8_t {1}_init_script_2[] =\n'.format(chipset,array_name)) + fout.write ('{\n') + second_part = True + + fout.write(line + '\n') + + if second_part: + fout.write('const uint32_t {0}_init_script_size = sizeof({0}_init_script) + sizeof({0}_init_script_2);\n'.format(array_name)) + else: + fout.write('const uint32_t {0}_init_script_size = sizeof({0}_init_script);\n'.format(array_name)) + fout.close() + print 'Created', filename + + +try: + f = open ('BTPSVEND.c', 'r') +except IOError as e: + print usage + sys.exit(1) + +# extract the CC2560 script first +extract_script(f, 'Patch', 'cc2560', 'cc256x') + +# then the CC2567 script +extract_script(f, 'PatchXETU', 'cc2567', 'cc256x') + +print '\nExtraction successful!\n' + + +