preparing extraction of examples into embedded folder

This commit is contained in:
matthias.ringwald@gmail.com 2014-11-06 23:11:45 +00:00
parent 2a7e8b9174
commit 018b47c77d
31 changed files with 5539 additions and 0 deletions

View File

@ -0,0 +1,138 @@
#
# Makefile for MSP-EXP430F5438 demos with PAN1315, PAN1317, PAN1325, PAN1323, or PAN1327 Bluetooth modules
#
# Please check instructions at https://code.google.com/p/btstack/wiki/CC256x on where to download the init scripts and how to convert them to *.c files.
#
# mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki
#
# init scripts
CC2560B = bluetooth_init_cc2560B_1.0_BT_Spec_4.1.o
CC2564B = bluetooth_init_cc2564B_1.0_BT_Spec_4.1.o
CC2567 = CC256x_BT_Service_Pack_2.8_ANT_1.16.o
BTSTACK_ROOT = ../..
VPATH += $(BTSTACK_ROOT)/ble
VPATH += $(BTSTACK_ROOT)/chipset-cc256x
VPATH += $(BTSTACK_ROOT)/example/embedded
VPATH += $(BTSTACK_ROOT)/src
CC = msp430-gcc
CFLAGS = -mmcu=msp430f5438a -Os -Wall -fno-toplevel-reorder -I. -I$(BTSTACK_ROOT)/include -I$(BTSTACK_ROOT)/src -I$(BTSTACK_ROOT)/ble -I$(BTSTACK_ROOT)/chipset-cc256x
LDFLAGS = -mmcu=msp430f5438a
CORE = \
hal_tick.c \
hal_cpu.c \
hal_board.c \
hal_compat.c \
hal_usb.c \
hci_dump.c \
btstack_memory.c \
linked_list.c \
memory_pool.c \
run_loop.c \
run_loop_embedded.c \
utils.c \
COMMON = \
hal_uart_dma.c \
bt_control_cc256x.c \
hci.c \
hci_cmds.c \
hci_transport_h4_ehcill_dma.c \
SPP = \
l2cap.c \
l2cap_signaling.c \
remote_device_db_memory.c \
rfcomm.c \
sdp_util.c \
sdp_parser.c \
sdp_client.c \
sdp_query_util.c \
sdp_query_rfcomm.c \
BLE = \
att.c \
att_server.c \
central_device_db_memory.c \
sm.c \
att_dispatch.c \
l2cap_le.c \
${CC2564B} \
# gatt_client.c \
LCD = hal_lcd.c hal_lcd_fonts.c
CORE_OBJ = $(CORE:.c=.o)
COMMON_OBJ = $(COMMON:.c=.o)
SPP_OBJ = $(SPP:.c=.o)
BLE_OBJ = $(BLE:.c=.o)
LCD_OBJ = $(LCD:.c=.o)
# create .hex file from .out
%.hex: %.out
msp430-objcopy -O ihex $< $@
# create firmware image from common objects and example source file
all: led_counter.hex spp_counter.hex spp_accel.hex gap_inquiry.hex spp_flowcontrol.hex \
sdp_rfcomm_query.hex sdp_general_query.hex ble_server.hex
# compiling requires a 20-bit mspgcc version
# hid_demo.hex
# spp_and_le_counter.hex
# compiling ant-test requires special ant init script
# ant-test.hex
# compile GATT database
%.h: %.gatt
python ${BTSTACK_ROOT}/ble/compile-gatt.py $< $@
led_counter.out: ${CORE_OBJ} led_counter.o
${CC} $^ ${LDFLAGS} -o $@
ant-test.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} profile.h sdp.o ant_cmds.o ${CC2567} ant-test.o
${CC} $^ ${LDFLAGS} -o $@
ble_server.out: ${CORE_OBJ} ${COMMON_OBJ} ${BLE_OBJ} ${LCD_OBJ} profile.h ble_server.o
${CC} $^ ${LDFLAGS} -o $@
hid_demo.out: ${CORE_OBJ} ${COMMON_OBJ} ${LCD_OBJ} ${SPP_OBJ} ${CC2560B} hid_demo.o
${CC} $^ ${LDFLAGS} -o $@
spp_accel.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_accel.o sdp.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
spp_and_le_counter.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${BLE_OBJ} spp_and_le_counter.h spp_and_le_counter.o sdp.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
spp_counter.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_counter.o sdp.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
spp_flowcontrol.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_flowcontrol.o sdp.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
gap_inquiry.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} gap_inquiry.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
sdp_rfcomm_query.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} sdp_rfcomm_query.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
sdp_general_query.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} sdp_general_query.o hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
clean:
rm -f $ *.o *.out *.hex profile.h spp_and_le_counter.h ../driver/*.o ../../src/*.o ../src/*.o ../firmware/*.o ${BTSTACK_ROOT}/chipset-cc256x/*.o ${BTSTACK_ROOT}/src/*.o
size: all
msp430-size ../firmware/*.o
msp430-size ../src/*.o
msp430-size ${BTSTACK_ROOT}/chipset-cc256x/*.o
msp430-size ${BTSTACK_ROOT}/src/*.o
msp430-size *.o
msp430-size *.out

View File

@ -0,0 +1,46 @@
/************************************************************************
Filename: UserExperienceGraphics.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef GRAPHICS_H
#define GRAPHICS_H
#define MAX_IMAGE 7
const unsigned int TI_TINY_BUG[]={
0xC000, 0x3FFF, 0x0000, 0x0000,
0xC000, 0x3FFF, 0x0000, 0x0000,
0xC000, 0x3FFF, 0x0000, 0x0000,
0xC000, 0x3FFF, 0x03F0, 0x0000,
0xC000, 0x3FFF, 0x03F0, 0x0000,
0xC000, 0xFFFF, 0x03F0, 0x0000,
0xC000, 0xFFFF, 0xF3C3, 0x00FF,
0xC000, 0xFFFF, 0xF0F0, 0x00FF,
0xC000, 0xFFFF, 0xFCFC, 0x00FF,
0xC000, 0xFFFF, 0xFCFC, 0x00FF,
0xC000, 0x03FF, 0xC0FC, 0x00FF,
0xC000, 0x03FF, 0xC0FF, 0x03FF,
0xFFFF, 0x03FF, 0xC0FF, 0x03FF,
0xFFFF, 0x3FFF, 0xFF3F, 0x0FFF,
0xFFFF, 0x3FFF, 0xFF3F, 0x0FFF,
0xFFFC, 0x3FFF, 0xFF3F, 0x0FFF,
0xFFF0, 0xCFFF, 0xFF3F, 0x0FFF,
0xFFC0, 0xCFFF, 0xFFCF, 0x0FFF,
0xFFC0, 0xCFFF, 0xFF0F, 0x0FFF,
0xFF00, 0x0FFF, 0xFC00, 0x03FF,
0xFF00, 0x0FC0, 0xFC00, 0x000F,
0x3C00, 0x3F00, 0xFF00, 0x0003,
0x0000, 0xFF00, 0x3FFF, 0x0000,
0x0000, 0xFF00, 0x0FFF, 0x0000,
0x0000, 0xFC00, 0x0FFF, 0x0000,
0x0000, 0xFC00, 0x03FF, 0x0000,
0x0000, 0xF000, 0x03FF, 0x0000,
0x0000, 0xF000, 0x03FF, 0x0000,
0x0000, 0xC000, 0x03FF, 0x0000,
0x0000, 0x0000, 0x03FF, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
};
#endif

View File

@ -0,0 +1,254 @@
// *****************************************************************************
//
// ant + spp demo - it provides a SPP port and and sends a counter every second
// - it also listens on ANT channel 33,1,1
//
// it doesn't use the LCD to get down to a minimal memory footpring
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/ant_cmds.h>
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include <btstack/sdp_util.h>
#include <btstack/utils.h>
#include "hci.h"
#include "l2cap.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "rfcomm.h"
#include "sdp.h"
#include "btstack-config.h"
#define HEARTBEAT_PERIOD_MS 1000
static uint8_t rfcomm_channel_nr = 1;
static uint16_t rfcomm_channel_id = 0;
static uint8_t spp_service_buffer[100];
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
uint8_t rfcomm_channel_nr;
uint16_t mtu;
uint8_t event_code;
// uint8_t channel;
uint8_t message_id;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo");
}
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
bt_flip_addr(event_addr, &packet[6]);
printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
// start ANT init
ant_send_cmd(&ant_reset);
break;
}
break;
case HCI_EVENT_LINK_KEY_REQUEST:
// deny link key request
printf("Link key request\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
break;
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printf("Pin code request - using '0000'\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
bt_flip_addr(event_addr, &packet[2]);
rfcomm_channel_nr = packet[8];
rfcomm_channel_id = READ_BT_16(packet, 9);
printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
rfcomm_accept_connection_internal(rfcomm_channel_id);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
if (packet[2]) {
printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
} else {
rfcomm_channel_id = READ_BT_16(packet, 12);
mtu = READ_BT_16(packet, 14);
printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
rfcomm_channel_id = 0;
break;
case 0xff: // vendor specific -> ANT
// vendor specific ant message
if (packet[2] != 0x00) break;
if (packet[3] != 0x05) break;
event_code = packet[7];
printf("ANT Event: ");
printf_hexdump(packet, size);
switch(event_code){
case MESG_STARTUP_MESG_ID:
// 2. assign channel
ant_send_cmd(&ant_assign_channel, 0, 0x00, 0);
break;
case MESG_RESPONSE_EVENT_ID:
// channel = packet[8];
message_id = packet[9];
switch (message_id){
case MESG_ASSIGN_CHANNEL_ID:
// 3. set channel ID
ant_send_cmd(&ant_channel_id, 0, 33, 1, 1);
break;
case MESG_CHANNEL_ID_ID:
// 4. open channel
ant_send_cmd(&ant_open_channel, 0);
}
break;
default:
break;
}
break;
default:
break;
}
break;
default:
break;
}
}
static void heartbeat_handler(struct timer *ts){
if (rfcomm_channel_id){
static int counter = 0;
char lineBuffer[30];
sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter);
printf(lineBuffer);
if (rfcomm_can_send_packet_now(rfcomm_channel_id)){
int err = rfcomm_send_internal(rfcomm_channel_id, (uint8_t*) lineBuffer, strlen(lineBuffer));
if (err) {
printf("rfcomm_send_internal -> error %d", err);
}
}
}
run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
run_loop_add_timer(ts);
}
// main
int main(void)
{
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
// init RFCOMM
rfcomm_init();
rfcomm_register_packet_handler(packet_handler);
rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 100); // reserved channel, mtu=100
// init SDP, create record for SPP and register with SDP
sdp_init();
memset(spp_service_buffer, 0, sizeof(spp_service_buffer));
service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer;
sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter");
printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record)));
sdp_register_service_internal(NULL, service_record_item);
// set one-shot timer
timer_source_t heartbeat;
heartbeat.process = &heartbeat_handler;
run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
run_loop_add_timer(&heartbeat);
printf("Run...\n\r");
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
hci_power_control(HCI_POWER_ON);
// default to discoverable
hci_discoverable_control(1);
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,318 @@
/*
* Copyright (C) 2011-2012 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.
* 4. This software may not be used in a commercial product
* without an explicit license granted by the copyright holder.
*
* 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.
*
*/
// *****************************************************************************
//
// att device demo
//
// *****************************************************************************
// TODO: seperate BR/EDR from LE ACL buffers
// TODO: move LE init into HCI
// ..
// NOTE: Supports only a single connection
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "btstack-config.h"
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include "hal_lcd.h"
#include "hal_usb.h"
#include "UserExperienceGraphics.h"
#include <btstack/run_loop.h>
#include "btstack_memory.h"
#include "bt_control_cc256x.h"
#include "hci.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "sm.h"
#include "att.h"
#include "att_server.h"
#include "gap_le.h"
#include "central_device_db.h"
#define FONT_HEIGHT 12 // Each character has 13 lines
#define FONT_WIDTH 8
#define MAX_CHR01_VALUE_LENGTH 40
static uint16_t chr01_value_length = 0;
static char chr01_value[MAX_CHR01_VALUE_LENGTH];
static char chr02_value = 0;
void doLCD(void){
//Initialize LCD and backlight
// 138 x 110, 4-level grayscale pixels.
halLcdInit();
// halLcdBackLightInit();
// halLcdSetBackLight(0); // 8 for normal
halLcdSetContrast(100);
halLcdClearScreen();
halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 );
halLcdPrintLine("BTstack on ", 0, 0);
halLcdPrintLine("TI MSP430", 1, 0);
halLcdPrintLine("LE Write Test", 2, 0);
halLcdPrintLine("NOT CONNECTED", 4, 0);
halLcdPrintLine("Attribute 0x0022:", 6, 0);
halLcdPrintLine("- NO VALUE -", 7, 0);
}
void overwriteLine(int line, char *text){
halLcdClearImage(130, FONT_HEIGHT, 0, line*FONT_HEIGHT);
halLcdPrintLine(text, line, 0);
}
// enable LE, setup ADV data
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
bd_addr_t addr;
uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff };
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
printf("Working!\n");
hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
}
break;
case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED:
if (packet[2]) {
overwriteLine(4, "CONNECTED");
} else {
overwriteLine(4, "NOT CONNECTED");
}
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
// restart advertising
hci_send_cmd(&hci_le_set_advertise_enable, 1);
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
bt_flip_addr(addr, &packet[6]);
printf("BD ADDR: %s\n", bd_addr_to_str(addr));
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){
hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data);
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){
hci_send_cmd(&hci_le_set_advertise_enable, 1);
break;
}
default:
break;
}
}
// test profile
#include "profile.h"
static uint16_t get_read_att_value_len(uint16_t att_handle){
uint16_t value_len;
switch(att_handle){
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
value_len = chr01_value_length;
break;
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
value_len = 1;
break;
default:
value_len = 0;
break;
}
return value_len;
}
static uint16_t get_write_att_value_len(uint16_t att_handle){
uint16_t value_len;
switch(att_handle){
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
value_len = MAX_CHR01_VALUE_LENGTH;
break;
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
value_len = 1;
break;
default:
value_len = 0;
break;
}
return value_len;
}
static uint16_t get_bytes_to_copy(uint16_t value_len, uint16_t offset, uint16_t buffer_size){
if (value_len <= offset ) return 0;
uint16_t bytes_to_copy = value_len - offset;
if (bytes_to_copy > buffer_size) {
bytes_to_copy = buffer_size;
}
return bytes_to_copy;
}
uint16_t att_read_callback(uint16_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
printf("READ Callback, handle %04x\n", att_handle);
uint16_t value_len = get_read_att_value_len(att_handle);
if (!buffer) return value_len;
uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset, buffer_size);
if (!bytes_to_copy) return 0;
switch(att_handle){
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
memcpy(buffer, &chr01_value[offset], bytes_to_copy);
break;
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
buffer[offset] = chr02_value;
break;
}
return bytes_to_copy;
}
// write requests
static int att_write_callback(uint16_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
printf("WRITE Callback, handle %04x\n", att_handle);
uint16_t value_len = get_write_att_value_len(att_handle);
uint16_t bytes_to_copy = get_bytes_to_copy(value_len, offset,buffer_size);
if (!bytes_to_copy) return ATT_ERROR_INVALID_OFFSET;
switch(att_handle){
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
buffer[buffer_size] = 0;
memcpy(&chr01_value[offset], buffer, bytes_to_copy);
chr01_value_length = bytes_to_copy + offset;
printf("New text: %s\n", buffer);
overwriteLine(7, (char*)buffer);
break;
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
printf("New value: %u\n", buffer[offset]);
if (buffer[offset]) {
LED_PORT_OUT |= LED_2;
} else {
LED_PORT_OUT &= ~LED_2;
}
chr02_value = buffer[offset];
break;
}
return 0;
}
// main
int main(void)
{
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// Debug UART
halUsbInit();
// show off
doLCD();
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
hci_init(transport, config, control, NULL);
// use eHCILL
// bt_control_cc256x_enable_ehcill(1);
// set up l2cap_le
l2cap_init();
// setup central device db
central_device_db_init();
// setup SM: Display only
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
// setup ATT server
att_server_init(profile_data, NULL, att_write_callback);
att_server_register_packet_handler(app_packet_handler);
printf("Run...\n\r");
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
hci_power_control(HCI_POWER_ON);
LED_PORT_OUT &= ~LED_2;
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,39 @@
#ifndef __BTSTACK_CONFIG
#define __BTSTACK_CONFIG
#define EMBEDDED
#define HAVE_BLE
#define HAVE_INIT_SCRIPT
#define HAVE_BZERO
#define HAVE_TICK
#define HAVE_EHCILL
#define HAVE_HCI_DUMP
// #define ENABLE_LOG_ERROR
// #define ENABLE_LOG_INFO
#define HCI_ACL_PAYLOAD_SIZE 52
//
#define MAX_SPP_CONNECTIONS 1
#define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS
#define MAX_NO_GATT_CLIENTS 0
#define MAX_NO_GATT_SUBCLIENTS 0
#define MAX_NO_L2CAP_SERVICES 2
#define MAX_NO_L2CAP_CHANNELS (1+MAX_SPP_CONNECTIONS)
#define MAX_NO_RFCOMM_MULTIPLEXERS MAX_SPP_CONNECTIONS
#define MAX_NO_RFCOMM_SERVICES 1
#define MAX_NO_RFCOMM_CHANNELS MAX_SPP_CONNECTIONS
#define MAX_NO_BNEP_SERVICES 1
#define MAX_NO_BNEP_CHANNELS MAX_SPP_CONNECTIONS
#define MAX_NO_DB_MEM_DEVICE_LINK_KEYS 2
#define MAX_NO_DB_MEM_DEVICE_NAMES 0
#define MAX_NO_DB_MEM_SERVICES 1
#endif

View File

@ -0,0 +1,248 @@
// *****************************************************************************
//
// minimal setup for HCI code
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include "hci.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "btstack-config.h"
#define MAX_DEVICES 10
enum DEVICE_STATE { REMOTE_NAME_REQUEST, REMOTE_NAME_INQUIRED, REMOTE_NAME_FETCHED };
struct device {
bd_addr_t address;
uint16_t clockOffset;
uint32_t classOfDevice;
uint8_t pageScanRepetitionMode;
uint8_t rssi;
enum DEVICE_STATE state;
};
#define INQUIRY_INTERVAL 5
struct device devices[MAX_DEVICES];
int deviceCount = 0;
enum STATE {INIT, W4_INQUIRY_MODE_COMPLETE, ACTIVE} ;
enum STATE state = INIT;
int getDeviceIndexForAddress( bd_addr_t addr){
int j;
for (j=0; j< deviceCount; j++){
if (BD_ADDR_CMP(addr, devices[j].address) == 0){
return j;
}
}
return -1;
}
void start_scan(void){
printf("Starting inquiry scan..\n");
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
}
int has_more_remote_name_requests(void){
int i;
for (i=0;i<deviceCount;i++) {
if (devices[i].state == REMOTE_NAME_REQUEST) return 1;
}
return 0;
}
void do_next_remote_name_request(void){
int i;
for (i=0;i<deviceCount;i++) {
// remote name request
if (devices[i].state == REMOTE_NAME_REQUEST){
devices[i].state = REMOTE_NAME_INQUIRED;
printf("Get remote name of %s...\n", bd_addr_to_str(devices[i].address));
hci_send_cmd(&hci_remote_name_request, devices[i].address,
devices[i].pageScanRepetitionMode, 0, devices[i].clockOffset | 0x8000);
return;
}
}
}
static void continue_remote_names(){
if (has_more_remote_name_requests()){
do_next_remote_name_request();
return;
}
start_scan();
}
static void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
bd_addr_t addr;
int i;
int index;
int numResponses;
// printf("packet_handler: pt: 0x%02x, packet[0]: 0x%02x\n", packet_type, packet[0]);
if (packet_type != HCI_EVENT_PACKET) return;
uint8_t event = packet[0];
switch(state){
case INIT:
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
state = W4_INQUIRY_MODE_COMPLETE;
}
break;
case W4_INQUIRY_MODE_COMPLETE:
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
start_scan();
state = ACTIVE;
}
break;
case ACTIVE:
switch(event){
case HCI_EVENT_INQUIRY_RESULT:
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{
numResponses = packet[2];
int offset = 3;
for (i=0; i<numResponses && deviceCount < MAX_DEVICES;i++){
bt_flip_addr(addr, &packet[offset]);
offset += 6;
index = getDeviceIndexForAddress(addr);
if (index >= 0) continue; // already in our list
memcpy(devices[deviceCount].address, addr, 6);
devices[deviceCount].pageScanRepetitionMode = packet[offset];
offset += 1;
if (event == HCI_EVENT_INQUIRY_RESULT){
offset += 2; // Reserved + Reserved
devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
offset += 3;
devices[deviceCount].clockOffset = READ_BT_16(packet, offset) & 0x7fff;
offset += 2;
devices[deviceCount].rssi = 0;
} else {
offset += 1; // Reserved
devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
offset += 3;
devices[deviceCount].clockOffset = READ_BT_16(packet, offset) & 0x7fff;
offset += 2;
devices[deviceCount].rssi = packet[offset];
offset += 1;
}
devices[deviceCount].state = REMOTE_NAME_REQUEST;
printf("Device found: %s with COD: 0x%06x, pageScan %d, clock offset 0x%04x, rssi 0x%02x\n", bd_addr_to_str(addr),
devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
devices[deviceCount].clockOffset, devices[deviceCount].rssi);
deviceCount++;
}
break;
}
case HCI_EVENT_INQUIRY_COMPLETE:
for (i=0;i<deviceCount;i++) {
// retry remote name request
if (devices[i].state == REMOTE_NAME_INQUIRED)
devices[i].state = REMOTE_NAME_REQUEST;
}
continue_remote_names();
break;
case BTSTACK_EVENT_REMOTE_NAME_CACHED:
bt_flip_addr(addr, &packet[3]);
printf("Cached remote name for %s: '%s'\n", bd_addr_to_str(addr), &packet[9]);
break;
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
bt_flip_addr(addr, &packet[3]);
index = getDeviceIndexForAddress(addr);
if (index >= 0) {
if (packet[2] == 0) {
printf("Name: '%s'\n", &packet[9]);
devices[index].state = REMOTE_NAME_FETCHED;
} else {
printf("Failed to get name: page timeout\n");
}
}
continue_remote_names();
break;
default:
break;
}
break;
default:
break;
}
}
static void hw_setup(void){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
// ready - enable irq used in h4 task
__enable_interrupt();
}
static void btstack_setup(void){
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
hci_register_packet_handler(packet_handler);
}
// main == setup
int btstack_main(void)
{
hw_setup();
btstack_setup();
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,430 @@
/**
* @file hal_adc.c
*
* Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#include "hal_adc.h"
#include <msp430x54x.h>
#include "hal_compat.h"
static int SavedADC12MEM0 = 0, SavedADC12MEM1 = 0, SavedADC12MEM2 = 0;
static int Acc_x = 0, Acc_y = 0, Acc_z = 0;
static int Acc_x_offset = 0, Acc_y_offset = 0, Acc_z_offset = 0;
static long int Vcc = 0, Temperature = 0;
static long int temperatureOffset = CELSIUS_OFFSET;
static unsigned char conversionType = CELSIUS, adcMode = ADC_OFF_MODE;
static unsigned char exit_active_from_ADC12 = 0;
/************************************************************************
* @brief Turns on and initializes ADC12, accelerometer in order to
* sample x, y, z-axis inputs.
*
* @param none
*
* @return none
*************************************************************************/
void halAccelerometerInit(void)
{
adcMode = ADC_ACC_MODE;
ACC_PORT_SEL |= ACC_X_PIN + ACC_Y_PIN; //Enable A/D channel inputs
ACC_PORT_DIR &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN);
ACC_PORT_DIR |= ACC_PWR_PIN; //Enable ACC_POWER
ACC_PORT_OUT |= ACC_PWR_PIN;
//Sequence of channels, once, ACLK
ADC12CTL0 = ADC12ON + ADC12SHT02 + ADC12MSC;
ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12SSEL_0;
ADC12CTL2 = ADC12RES_2;
ADC12MCTL0 = ACC_X_CHANNEL;
ADC12MCTL1 = ACC_Y_CHANNEL;
ADC12MCTL2 = ACC_Z_CHANNEL + ADC12EOS;
// Allow the accelerometer to settle before sampling any data
// 4.5.3-20110706-2 doesn't allow for 32-bit delay cycles
int i;
for (i=0;i<10;i++){
__delay_cycles(20000);
}
UCSCTL8 |= MODOSCREQEN;
}
/************************************************************************
* @brief Calibrates the offset values for x, y, and z axes.
*
* @param none
*
* @return none
*************************************************************************/
void halAccelerometerCalibrate(void)
{
unsigned char tempQuit;
tempQuit = exit_active_from_ADC12;
halAdcSetQuitFromISR( 1 );
halAdcStartRead();
__bis_SR_register(LPM3_bits + GIE);
__no_operation();
halAccelerometerReadWithOffset(&Acc_x_offset, &Acc_y_offset, &Acc_z_offset);
halAdcSetQuitFromISR( tempQuit );
}
/************************************************************************
* @brief Set function for the calibrated offsets for the x, y, and z axes.
*
* @param x Calibrated offset for the x-axis
*
* @param y Calibrated offset for the y-axis
*
* @param z Calibrated offset for the z-axis
*
* @return none
*************************************************************************/
void halAccelerometerSetCalibratedOffset( int x, int y, int z )
{
Acc_x_offset = x;
Acc_y_offset = y;
Acc_z_offset = z;
}
/************************************************************************
* @brief Get function for the x, y, and z axes calibrated offsets
*
* @param x Pointer to the calibrated offset for the x-axis
*
* @param y Pointer to the calibrated offset for the y-axis
*
* @param z Pointer to the calibrated offset for the z-axis
*
* @return none
*************************************************************************/
void halAccelerometerGetCalibratedOffset(int *x, int *y, int *z)
{
*x = Acc_x_offset;
*y = Acc_y_offset;
*z = Acc_y_offset;
}
/************************************************************************
* @brief Get function for the x, y, and z accelerometer samples,
* including the calibrated offsets.
*
* @param x Pointer to the accelerometer reading (x-axis)
*
* @param y Pointer to the accelerometer reading (y-axis)
*
* @param z Pointer to the accelerometer reading (z-axis)
*
* @return none
*************************************************************************/
void halAccelerometerRead(int *x, int *y, int *z)
{
Acc_x = SavedADC12MEM0;
Acc_y = SavedADC12MEM1;
Acc_z = SavedADC12MEM2;
*x = Acc_x - Acc_x_offset;
*y = Acc_y - Acc_y_offset;
*z = Acc_z - Acc_z_offset;
}
/************************************************************************
* @brief Get function for the x, y, and z accelerometer samples,
* excluding the calibrated offsets.
*
* @param x Pointer to the accelerometer reading (x-axis)
*
* @param y Pointer to the accelerometer reading (y-axis)
*
* @param z Pointer to the accelerometer reading (z-axis)
*
* @return none
*************************************************************************/
void halAccelerometerReadWithOffset(int *x, int *y, int *z)
{
*x = SavedADC12MEM0;
*y = SavedADC12MEM1;
*z = SavedADC12MEM2;
}
/************************************************************************
* @brief Disables the ADC12, accelerometer that sampled x, y, z-axis inputs.
*
* @param none
*
* @return none
*************************************************************************/
void halAccelerometerShutDown(void)
{
//Turn off ADC Module
ADC12CTL0 &= ~( ADC12ON + ADC12ENC );
ACC_PORT_OUT &= ~ACC_PWR_PIN; //Disable ACC_POWER
//Disable A/D channel inputs
ACC_PORT_SEL &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN);
ACC_PORT_DIR |= (ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN + ACC_PWR_PIN);
ACC_PORT_OUT &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN + ACC_PWR_PIN);
adcMode = ADC_OFF_MODE;
}
/*----------------------------------------------------------------------------*/
/************************************************************************
* @brief Intializes the ADC12 to sample Temperature and Vcc.
*
* @param none
*
* @return none
*************************************************************************/
void halAdcInitTempVcc(void)
{
//Sequence of channels, once,
adcMode = ADC_TEMP_MODE;
UCSCTL8 |= MODOSCREQEN;
ADC12CTL0 = ADC12ON + ADC12SHT0_15 + ADC12MSC + + ADC12REFON + ADC12REF2_5V;
ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12SSEL_0;
ADC12CTL2 = ADC12RES_2;
ADC12MCTL0 = ADC12SREF_1 + TEMP_CHANNEL;
ADC12MCTL1 = ADC12SREF_1 + VCC_CHANNEL + ADC12EOS;
}
/************************************************************************
* @brief Turns off / disable the ADC12.
*
* @param none
*
* @return none
*************************************************************************/
void halAdcShutDownTempVcc(void)
{
ADC12CTL0 &= ~ ( ADC12ON + ADC12ENC + ADC12REFON );
adcMode = ADC_OFF_MODE;
}
/************************************************************************
* @brief Sets the conversion type to either Farenheit (F) or Celsius (C).
*
* @param conversion The #define constant CELSIUS or FAHRENHEIT.
*
* @return none
*************************************************************************/
void halAdcSetTempConversionType(unsigned char conversion)
{
conversionType = conversion;
}
/************************************************************************
* @brief Set function for the calibrated temperature offset.
*
* @param offset The temperature offset.
*
* @return none
*************************************************************************/
void halAdcSetTempOffset(long offset)
{
temperatureOffset = offset;
}
/************************************************************************
* @brief Get function for the current temperature value.
*
* @param none
*
* @return The current temperature value.
*************************************************************************/
int halAdcGetTemp(void)
{
return Temperature;
}
/************************************************************************
* @brief Get function for the current Vcc value.
*
* @param none
*
* @return The current Vcc value.
*************************************************************************/
int halAdcGetVcc(void)
{
return Vcc;
}
/************************************************************************
* @brief Converts the Vcc and Temp readings from the ADC to BCD format.
*
* @param none
*
* @return none
*************************************************************************/
void halAdcConvertTempVccFromADC(void)
{
long multiplier, offset;
// Convert Vcc
Vcc = SavedADC12MEM1;
Vcc = Vcc * 50;
Vcc = Vcc / 4096;
// Convert Temperature
if (conversionType == CELSIUS)
{
multiplier = CELSIUS_MUL;
offset = temperatureOffset;
}
else
{
multiplier = (long) CELSIUS_MUL * 9 /5 ;
offset = (long) temperatureOffset * 9 / 5 - 320;
}
Temperature = (long) SavedADC12MEM0 * multiplier/4096 - offset;
}
/************************************************************************
* @brief Get function for the temperature and Vcc samples in "xxx^C/F" and
* "x.xV" format.
*
* @param TemperatureStr The string that holds the temperature reading
*
* @param Vcc The string that holds the Vcc reading
*
* @return none
*************************************************************************/
void halAdcReadTempVcc(char *TemperatureStr, char *VccStr)
{
unsigned char i, leadingZero = 0;
long int dummyTemperature, dummyVcc;
halAdcConvertTempVccFromADC();
dummyTemperature = Temperature;
dummyVcc = Vcc;
for (i = 0; i < 6; i++)
TemperatureStr[i] = '\0';
i=0;
//Check for negative
if (Temperature < 0)
{
TemperatureStr[i++]='-';
Temperature = -Temperature;
}
TemperatureStr[i] ='0';
if (Temperature >= 1000)
{
TemperatureStr[i]='1';
Temperature -=1000;
leadingZero = 1;
}
if (leadingZero == 1)
i++;
//100s digit
TemperatureStr[i] = '0';
if (Temperature >= 100)
{
do
{
TemperatureStr[i]++;
Temperature -=100;
}
while (Temperature >=100);
leadingZero = 1;
}
if (leadingZero == 1)
i++;
//10s digit
TemperatureStr[i] = '0';
if (Temperature >=10)
{
do
{
TemperatureStr[i]++;
Temperature -=10;
}
while (Temperature >=10);
}
TemperatureStr[++i] = '^';
if (conversionType == CELSIUS)
TemperatureStr[++i]='C';
else
TemperatureStr[++i]='F';
VccStr[0] = '0';
VccStr[2] = '0';
while (Vcc >= 10)
{
VccStr[0]++;
Vcc -= 10;
}
VccStr[2] += Vcc;
Temperature = dummyTemperature;
Vcc = dummyVcc;
}
/*----------------------------------------------------------------------------*/
/************************************************************************
* @brief Starts the ADC conversion.
*
* @param none
*
* @return none
*************************************************************************/
void halAdcStartRead(void)
{
ADC12IFG &= ~(BIT1+BIT0); // Clear any pending flags
if (adcMode == ADC_ACC_MODE)
{
ADC12CTL0 |= ADC12ENC | ADC12SC ;
ADC12IE |= BIT2;
}
else
{
ADC12CTL0 |= ADC12REFON; // Turn on ADC12 reference
// Delay to stabilize ADC12 reference assuming the fastest MCLK of 18 MHz.
// 35 us = 1 / 18 MHz * 630
__delay_cycles(630);
ADC12IE |= BIT1; // Enable interrupt
ADC12CTL0 |= ADC12ENC | ADC12SC;
}
}
/************************************************************************
* @brief Sets the flag that causes an exit into active CPU mode from
* the ADC12 ISR.
*
* @param quit
*
* - 1 - Exit active from ADC12 ISR
* - 0 - Remain in LPMx on exit from ADC12ISR
*
* @return none
*************************************************************************/
void halAdcSetQuitFromISR(unsigned char quit)
{
exit_active_from_ADC12 = quit;
}
/*----------------------------------------------------------------------------*/
#ifdef __GNUC__
__attribute__((interrupt(ADC12_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=ADC12_VECTOR
__interrupt
#endif
void ADC12_ISR(void)
{
SavedADC12MEM0 = ADC12MEM0; // Store the sampled data
SavedADC12MEM1 = ADC12MEM1;
SavedADC12MEM2 = ADC12MEM2;
ADC12IFG = 0; // Clear the interrupt flags
ADC12CTL0 &= ~( ADC12ENC | ADC12SC | ADC12REFON);
if (exit_active_from_ADC12) __bic_SR_register_on_exit(LPM3_bits);
}

View File

@ -0,0 +1,83 @@
/*******************************************************************************
Filename: hal_adc.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef HAL_ADC_H
#define HAL_ADC_H
#define ACC_PWR_PIN BIT0
#define ACC_PORT_DIR P6DIR
#define ACC_PORT_OUT P6OUT
#define ACC_PORT_SEL P6SEL
#define ACC_X_PIN BIT1
#define ACC_Y_PIN BIT2
#define ACC_Z_PIN BIT3
#define ACC_X_CHANNEL ADC12INCH_1
#define ACC_Y_CHANNEL ADC12INCH_2
#define ACC_Z_CHANNEL ADC12INCH_3
#define TEMP_CHANNEL ADC12INCH_10
#define VCC_CHANNEL ADC12INCH_11
#define AUDIO_PORT_DIR P6DIR
#define AUDIO_PORT_OUT P6OUT
#define AUDIO_PORT_SEL P6SEL
#define MIC_POWER_PIN BIT4
#define MIC_INPUT_PIN BIT5
#define MIC_INPUT_CHAN ADC12INCH_5
#define AUDIO_OUT_PWR_PIN BIT6
#define AUDIO_OUT_DIR P4DIR
#define AUDIO_OUT_OUT P4OUT
#define AUDIO_OUT_SEL P4SEL
#define AUDIO_OUT_PIN BIT4
#define ACC_X_THRESHOLD 200
#define ACC_Y_THRESHOLD 200
#define ACC_X_MAX 1000
#define ACC_Y_MAX 1000
#define ACC_Z_MAX 1000
#define ACC_X_LOW_OFFSET 1950
#define ACC_X_HIGH_OFFSET 2150
#define ACC_Y_LOW_OFFSET 1950
#define ACC_Y_HIGH_OFFSET 2150
#define ACC_Z_LOW_OFFSET 1950
#define ACC_Z_HIGH_OFFSET 2150
#define CELSIUS 0xFF
#define FAHRENHEIT 0x00
#define CELSIUS_MUL 7040
#define CELSIUS_OFFSET 2620
#define FAHRENHEIT_MUL 12672
#define FAHRENHEIT_OFFSET 3780
enum { ADC_OFF_MODE, ADC_ACC_MODE, ADC_TEMP_MODE};
/*-------------Accelerometer Functions----------------------------------------*/
void halAccelerometerInit(void);
void halAccelerometerCalibrate(void);
void halAccelerometerSetCalibratedOffset( int x, int y, int z );
void halAccelerometerGetCalibratedOffset(int *x, int *y, int*z);
void halAccelerometerRead(int* x, int* y, int* z);
void halAccelerometerReadWithOffset(int* x, int* y, int* z);
void halAccelerometerShutDown(void);
/*-------------Temperature & VCC Functions------------------------------------*/
void halAdcInitTempVcc(void);
void halAdcShutDownTempVcc(void);
void halAdcSetTempConversionType(unsigned char conversion);
void halAdcSetTempOffset(long offset);
int halAdcGetTemp(void);
int halAdcGetVcc(void);
void halAdcConvertTempVccFromADC(void);
void halAdcReadTempVcc(char *TemperatureStr, char *VccStr);
/*-------------Generic ADC12 Functions----------------------------------------*/
void halAdcStartRead(void);
void halAdcSetQuitFromISR(unsigned char quit);
#endif

View File

@ -0,0 +1,367 @@
/**
* @file hal_board.c
*
* Copyright 2008 Texas Instruments, Inc.
******************************************************************************/
#include "hal_board.h"
#include "msp430x54x.h"
#include "hal_compat.h"
#include "hal_adc.h"
#include "hal_usb.h"
static void halBoardSetVCoreUp(unsigned char level);
static void halBoardSetVCoreDown(unsigned char level);
static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
unsigned char *setDcoRange,
unsigned char *setVCore,
unsigned int *setMultiplier);
/************************************************************************
* @brief Increments the VCore setting.
*
* @param level The target VCore setting
*
* @return none
*************************************************************************/
static void halBoardSetVCoreUp (unsigned char level)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
// Set SVS/M high side to new level
SVSMHCTL = (SVSMHCTL & ~(SVSHRVL0*3 + SVSMHRRL0)) | \
(SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level);
// Set SVM new Level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Set SVS/M low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSMLRRL_3)) | (SVMLE + SVSMLRRL0 * level);
while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
PMMCTL0_L = PMMCOREV0 * level; // Set VCore to x
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); // Clear already set flags
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0); // Wait till level is reached
// Set SVS/M Low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
(SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
// Lock PMM module registers from write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Decrements the VCore setting.
*
* @param level The target VCore.
*
* @return none
*************************************************************************/
static void halBoardSetVCoreDown(unsigned char level)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
// Set SVS/M low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
(SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
PMMCTL0_L = (level * PMMCOREV0); // Set VCore to new level
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Get function for the DCORSEL, VCORE, and DCO multiplier settings
* that map to a given clock speed.
*
* @param systemClockSpeed Target DCO frequency - SYSCLK_xxMHZ.
*
* @param setDcoRange Pointer to the DCO range select bits.
*
* @param setVCore Pointer to the VCore level bits.
*
* @param setMultiplier Pointer to the DCO multiplier bits.
*
* @return none
************************************************************************/
static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
unsigned char *setDcoRange,
unsigned char *setVCore,
unsigned int *setMultiplier)
{
switch (systemClockSpeed)
{
case SYSCLK_1MHZ:
*setDcoRange = DCORSEL_1MHZ;
*setVCore = VCORE_1MHZ;
*setMultiplier = DCO_MULT_1MHZ;
break;
case SYSCLK_4MHZ:
*setDcoRange = DCORSEL_4MHZ;
*setVCore = VCORE_4MHZ;
*setMultiplier = DCO_MULT_4MHZ;
break;
case SYSCLK_8MHZ:
*setDcoRange = DCORSEL_8MHZ;
*setVCore = VCORE_8MHZ;
*setMultiplier = DCO_MULT_8MHZ;
break;
case SYSCLK_12MHZ:
*setDcoRange = DCORSEL_12MHZ;
*setVCore = VCORE_12MHZ;
*setMultiplier = DCO_MULT_12MHZ;
break;
case SYSCLK_16MHZ:
*setDcoRange = DCORSEL_16MHZ;
*setVCore = VCORE_16MHZ;
*setMultiplier = DCO_MULT_16MHZ;
break;
/*-------------------------------------
* Commented out because fmax = 18 MHz
* ------------------------------------
case SYSCLK_20MHZ:
*setDcoRange = DCORSEL_20MHZ;
*setVCore = VCORE_20MHZ;
*setMultiplier = DCO_MULT_20MHZ;
break;
case SYSCLK_25MHZ:
*setDcoRange = DCORSEL_25MHZ;
*setVCore = VCORE_25MHZ;
*setMultiplier = DCO_MULT_25MHZ;
break;
*-------------------------------------*/
}
}
/************************************************************************
* @brief Set function for the PMM core voltage (PMMCOREV) setting
*
* @param level Target VCore setting
*
* @return none
*************************************************************************/
void halBoardSetVCore(unsigned char level)
{
unsigned int currentVCore;
currentVCore = PMMCTL0 & PMMCOREV_3; // Get actual VCore
// Change VCore step by step
while (level != currentVCore)
{
if (level > currentVCore)
halBoardSetVCoreUp(++currentVCore);
else
halBoardSetVCoreDown(--currentVCore);
}
}
/************************************************************************
* @brief Disables all supply voltage supervision and monitoring.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardDisableSVS(void)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
SVSMLCTL &= ~( SVMLE + SVSLE + SVSLFP + SVMLFP ); // Disable Low side SVM
SVSMHCTL &= ~( SVMHE + SVSHE + SVSHFP + SVMHFP ); // Disable High side SVM
PMMCTL1 = PMMREFMD;
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Enables all supply voltage supervision and monitoring
*
* @param none
*
* @return none
*************************************************************************/
void halBoardEnableSVS(void)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
/*-----------
* NOTE: To attain the expected < 6 us wakeup from LPM modes, the following
* two lines must be commented out due to the fact that the PMM will hold
* the CPU until the reference is fully settled.
*----------*/
SVSMHCTL &= ~(SVSHFP+SVMHFP); // Disable full-performance mode
SVSMLCTL &= ~(SVSLFP+SVMLFP); // Disable full-performance mode
SVSMLCTL |= ( SVMLE + SVSLE); // Enable Low side SVM
SVSMHCTL |= ( SVMHE + SVSHE); // Enable High side SVM
PMMCTL1 &= ~PMMREFMD;
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Initialization routine for XT1.
*
* Sets the necessary internal capacitor values and loops until all
* ocillator fault flags remain cleared.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardStartXT1(void)
{
// Set up XT1 Pins to analog function, and to lowest drive
P7SEL |= 0x03;
UCSCTL6 |= XCAP_3 ; // Set internal cap values
while(SFRIFG1 & OFIFG) { // Check OFIFG fault flag
while ( (SFRIFG1 & OFIFG)) // Check OFIFG fault flag
{
// Clear OSC fault flags
UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
UCSCTL6 &= ~(XT1DRIVE1_L+XT1DRIVE0); // Reduce the drive strength
}
}
/************************************************************************
* @brief Set function for MCLK frequency.
*
* @param systemClockSpeed Intended frequency of operation - SYSCLK_xxMHZ.
*
* @return none
*************************************************************************/
void halBoardSetSystemClock(unsigned char systemClockSpeed)
{
unsigned char setDcoRange = 0;
unsigned char setVCore = 0;
unsigned int setMultiplier = 0;
halBoardGetSystemClockSettings( systemClockSpeed, &setDcoRange, \
&setVCore, &setMultiplier);
if (setVCore > (PMMCTL0 & PMMCOREV_3)) // Only change VCore if necessary
halBoardSetVCore( setVCore );
UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
UCSCTL1 = setDcoRange; // Select suitable range
UCSCTL2 = setMultiplier + FLLD_1; // Set DCO Multiplier
UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ;
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
// for optimization.
// 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
// t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
// __delay_cycles(562500);
int i;
for (i=0;i<10;i++){
__delay_cycles(56250);
}
}
/************************************************************************
* @brief Initializes ACLK, MCLK, SMCLK outputs on P11.0, P11.1,
* and P11.2, respectively.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardOutputSystemClock(void)
{
P11DIR |= 0x07;
P11SEL |= 0x07;
}
/************************************************************************
* @brief Stops the output of ACLK, MCLK, SMCLK on P11.0, P11.1, and P11.2.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardStopOutputSystemClock(void)
{
P11OUT &= ~0x07;
P11DIR |= 0x07;
P11SEL &= ~0x07;
}
/************************************************************************
* @brief Initializes all GPIO configurations.
* TI example did set all ports to OUTPUT, we don't.
* @param none
*
* @return none
*************************************************************************/
void halBoardInit(void)
{
#if 0
// ORIGINAL EP
//Tie unused ports
PAOUT = 0;
PADIR = 0xFFFF;
PASEL = 0;
PBOUT = 0;
PBDIR = 0xFFFF;
PBSEL = 0;
PCOUT = 0;
PCDIR = 0xFFFF;
PCSEL = 0;
PDOUT = 0;
PDDIR = 0xFFFF;
PDSEL = 0;
PEOUT = 0;
PEDIR = 0xFEFF; // P10.0 to USB RST pin,
// ...if enabled with J5
PESEL = 0;
P11OUT = 0;
P11DIR = 0xFF;
PJOUT = 0;
PJDIR = 0xFF;
P11SEL = 0;
#else
//Tie unused ports
PAOUT = 0;
PADIR = 0;
PASEL = 0;
PBOUT = 0;
PBDIR = 0;
PBSEL = 0;
PCOUT = 0;
PCDIR = 0;
PCSEL = 0;
PDOUT = 0;
PDDIR = 0;
PDSEL = 0;
PEOUT = 0;
PEDIR = 0;
PESEL = 0;
P11OUT = 0;
P11DIR = 0;
PJOUT = 0;
PJDIR = 0;
P11SEL = 0;
#endif
AUDIO_PORT_OUT = AUDIO_OUT_PWR_PIN ;
USB_PORT_DIR &= ~USB_PIN_RXD; // USB RX Pin, Input with
// ...pulled down Resistor
USB_PORT_OUT &= ~USB_PIN_RXD;
USB_PORT_REN |= USB_PIN_RXD;
}

View File

@ -0,0 +1,86 @@
/************************************************************************
Filename: hal_board.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef HAL_BOARD_H
#define HAL_BOARD_H
#define LED_PORT_DIR P1DIR
#define LED_PORT_OUT P1OUT
#define LED_1 BIT0
#define LED_2 BIT1
#define CLK_PORT_DIR P11DIR
#define CLK_PORT_OUT P11OUT
#define CLK_PORT_SEL P11SEL
#define ACLK_PIN BIT0
#define MCLK_PIN BIT1
#define SMCLK_PIN BIT2
#define XT1_XTAL_DIR P7DIR
#define XT1_XTAL_SEL P7SEL
#define XT1_XTAL_OUT P7OUT
#define SYSCLK_1MHZ 0
#define SYSCLK_4MHZ 1
#define SYSCLK_8MHZ 2
#define SYSCLK_12MHZ 3
#define SYSCLK_16MHZ 4
#define SYSCLK_20MHZ 5
#define SYSCLK_25MHZ 6
#define DCO_MULT_1MHZ 30
#define DCO_MULT_4MHZ 122
#define DCO_MULT_8MHZ 244
#define DCO_MULT_12MHZ 366
#define DCO_MULT_16MHZ 488
#define DCO_MULT_20MHZ 610
#define DCO_MULT_25MHZ 763
#define DCORSEL_1MHZ DCORSEL_2
#define DCORSEL_4MHZ DCORSEL_4
#define DCORSEL_8MHZ DCORSEL_4
#define DCORSEL_12MHZ DCORSEL_5
#define DCORSEL_16MHZ DCORSEL_5
#define DCORSEL_20MHZ DCORSEL_6
#define DCORSEL_25MHZ DCORSEL_7
// Due to erratum FLASH28 the expected VCORE settings, as follows,
// cannot be achieved. The Vcore setting should not be changed.
//#define VCORE_1MHZ PMMCOREV_0
//#define VCORE_4MHZ PMMCOREV_0
//#define VCORE_8MHZ PMMCOREV_0
//#define VCORE_12MHZ PMMCOREV_0
//#define VCORE_16MHZ PMMCOREV_1
//#define VCORE_20MHZ PMMCOREV_2
//#define VCORE_25MHZ PMMCOREV_3
#define VCORE_1MHZ PMMCOREV_2
#define VCORE_4MHZ PMMCOREV_2
#define VCORE_8MHZ PMMCOREV_2
#define VCORE_12MHZ PMMCOREV_2
#define VCORE_16MHZ PMMCOREV_2
// Due to erratum FLASH28 the expected VCORE settings, as follows,
// cannot be achieved. The Vcore setting should not be changed.
//#define VCORE_1_35V PMMCOREV_0
//#define VCORE_1_55V PMMCOREV_1
#define VCORE_1_75V PMMCOREV_2
//#define VCORE_1_85V PMMCOREV_3
/*----------------------------------------------------------------
* Function Prototypes
*----------------------------------------------------------------
*/
void halBoardSetVCore(unsigned char level);
void halBoardDisableSVS(void);
void halBoardEnableSVS(void);
void halBoardStartXT1(void);
void halBoardSetSystemClock(unsigned char systemClockSpeed);
void halBoardOutputSystemClock(void);
void halBoardStopOutputSystemClock(void);
void halBoardInit(void);
#endif

View File

@ -0,0 +1,45 @@
/**
* various functions to deal with flaws and portability issues
*
* @author Matthias Ringwald
*/
#include "hal_compat.h"
#include <msp430x54x.h>
// __delay_cycles is limited
void waitAboutOneSecond(void){
int i;
for (i=0;i<1000;i++) __delay_cycles(16000);
}
// access far text for MSP430X platform
#if defined(__GNUC__) && (__MSP430X__ > 0)
uint8_t FlashReadByte (uint32_t addr){
uint8_t result;
uint32_t register sr, flash;
__asm__ __volatile__ (
"mov r2 , %1 \n"
"bic %3 , r2 \n"
"nop \n"
"movx.a %4 , %2 \n"
"movx.b @%2, %0 \n"
"mov %1 , r2 \n"
:"=X"(result),"=r"(sr),"=r"(flash)
:"i"(GIE),"m"(addr));
return result;
}
// argument order matches memcpy
void FlashReadBlock(uint8_t *buffer, uint32_t addr, uint16_t len){
while (len){
*buffer++ = FlashReadByte(addr++);
len--;
}
}
#endif

View File

@ -0,0 +1,25 @@
/**
* various functions to deal with flaws and portability issues
*
* @author Matthias Ringwald
*/
// mspgcc LTS doesn't support 20-bit pointer yet -> put const data into .fartext
#ifndef __HAL_COMPAT_H
#define __HAL_COMPAT_H
#include <stdint.h>
void waitAboutOneSecond(void);
// single byte read
uint8_t FlashReadByte (uint32_t addr);
// argument order matches memcpy
void FlashReadBlock(uint8_t *buffer, uint32_t addr, uint16_t len);
#endif // __HAL_COMPAT_H

View File

@ -0,0 +1,86 @@
/*
* 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.
*
*/
/*
* hal_cpu.c
*
* Implementation for MSP430 Experimenter board using low power mode 0/3
*
*/
#include <btstack/hal_cpu.h>
#include "hal_board.h"
#include "hal_compat.h"
#include <msp430x54x.h>
static uint8_t low_power_mode_for_sleep = LPM0_bits;
void hal_cpu_disable_irqs(){
// LED off
LED_PORT_OUT &= ~LED_1;
// disable irq
__bic_SR_register(GIE);
}
void hal_cpu_enable_irqs(){
// enable irq
__bis_SR_register(GIE);
// LED on
LED_PORT_OUT |= LED_1;
}
void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled){
if (enabled){
LED_PORT_OUT |= LED_2;
low_power_mode_for_sleep = LPM0_bits;
return;
}
LED_PORT_OUT &= ~LED_2;
low_power_mode_for_sleep = LPM3_bits;
}
void hal_cpu_enable_irqs_and_sleep(){
// enable irq and enter lpm0
__bis_SR_register(low_power_mode_for_sleep + GIE);
// LED on
P1OUT |= 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
/*******************************************************************************
Filename: hal_lcd.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef HAL_LCD_H
#define HAL_LCD_H
#ifndef MIN
#define MIN(n,m) (((n) < (m)) ? (n) : (m))
#endif
#ifndef MAX
#define MAX(n,m) (((n) < (m)) ? (m) : (n))
#endif
#ifndef ABS
#define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
#define LCD_COMM_OUT P8OUT
#define LCD_COMM_DIR P8DIR
#define LCD_COMM_SEL P8SEL
#define LCD_BACKLIGHT_PIN BIT3
#ifdef REV_02
#define LCD_CS_RST_DIR LCD_COMM_DIR
#define LCD_CS_RST_OUT LCD_COMM_OUT
#define LCD_CS_PIN BIT1
#define LCD_RESET_PIN BIT2
#else
#define LCD_CS_RST_DIR P9DIR
#define LCD_CS_RST_OUT P9OUT
#define LCD_CS_PIN BIT6
#define LCD_RESET_PIN BIT7
#endif
#define LCD_ROW 110
#define LCD_COL 138
#define LCD_Size 3505
#define LCD_MEM_Size 110*17
#define LCD_Max_Column_Offset 0x10
#define LCD_Last_Pixel 3505
#define LCD_MEM_Row 0x11
#define LCD_Row 0x20
// Grayscale level definitions
#define PIXEL_OFF 0
#define PIXEL_LIGHT 1
#define PIXEL_DARK 2
#define PIXEL_ON 3
#define INVERT_TEXT BIT0
#define OVERWRITE_TEXT BIT2
/*-------------------------------------------------------------
* Function Prototypes
* ------------------------------------------------------------*/
void halLcdInit(void);
void halLcdShutDown(void);
void halLcdBackLightInit(void);
void halLcdSetBackLight(unsigned char BackLightLevel);
unsigned int halLcdGetBackLight(void);
void halLcdShutDownBackLight(void);
void halLcdSendCommand(unsigned char Data[]) ;
void halLcdSetContrast(unsigned char ContrastLevel);
unsigned char halLcdGetContrast(void);
void halLcdStandby(void);
void halLcdActive(void);
//Move to specified LCD address
void halLcdSetAddress(int Address);
//Draw at current segment location
void halLcdDrawCurrentBlock(unsigned int Value);
//Draw at specified location by calling
//LCD_Set_Address(Address) & LCD_Draw_Current_Block( value )
void halLcdDrawBlock(unsigned int Address, unsigned int Value);
//Read value from LCD CGRAM
int halLcdReadBlock(unsigned int Address);
//Clear LCD Screen
void halLcdClearScreen(void);
//Invert black to white and vice versa
void halLcdReverse(void);
// Draw a Pixel @ (x,y) with GrayScale level
void halLcdPixel( int x, int y, unsigned char GrayScale);
//Draw Line from (x1,y1) to (x2,y2) with GrayScale level
void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale);
void halLcdCircle(int x, int y, int Radius, int GrayScale);
void halLcdImage(const unsigned int Image[], int Columns, int Rows, int x, int y);
void halLcdClearImage(int Columns, int Rows, int x, int y);
//Print String of Length starting at current LCD location
void halLcdPrint( char String[], unsigned char TextStyle) ;
//Print String of Length starting at (x,y)
void halLcdPrintXY(char String[], int x, int y, unsigned char TextStyle);
//Print String of Length starting at (x,y)
void halLcdPrintLine(char String[], unsigned char Line, unsigned char TextStyle);
void halLcdPrintLineCol(char String[], unsigned char Line, unsigned char Col, unsigned char TextStyle);
void halLcdCursor(void);
void halLcdCursorOff(void);
//Scroll a single row of pixels
void halLcdScrollRow(int y);
//Scroll a number of consecutive rows from yStart to yEnd
void halLcdHScroll(int yStart, int yEnd);
//Scroll a line of text
void halLcdScrollLine(int Line);
#endif

View File

@ -0,0 +1,174 @@
/*******************************************************************************
Filename: hal_lcd_fonts.c
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#include "hal_lcd_fonts.h"
const uint8_t fonts_lookup[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
64,65,0,69,0,68,67,0,0,1, //'0' = 48 = 0x30
2,3,4,5,6,7,8,9,66,0, //'9' = 57 = 0x39
0,70,0,62,0,10,11,12,13,14, //'A' --> 'Z'
15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,
35,0,0,0,71,0,0,36,37,38, //'a' = 97
39,40,41,42,43,44,45,46,47,48,
49,50,51,52,53,54,55,56,57,58,
59,60,61,62,0 ,0, 0, 72,73,74,
75,76,77,78,79,80,81 //'z' = 122
};
const uint16_t fonts[]= {
0x0000, 0x0ffc, 0x3c0f, 0x3f0f, 0x3fcf, 0x3ccf, 0x3cff, 0x3c3f,
0x3c0f, 0x0ffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x00c0, 0x00f0,
0x00ff, 0x00f0, 0x00f0, 0x00f0, 0x00f0, 0x00f0, 0x0fff, 0x0000,
0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f00, 0x03c0,
0x00f0, 0x003c, 0x0f0f, 0x0fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x03fc, 0x0f0f, 0x0f00, 0x0f00, 0x03f0, 0x0f00, 0x0f00, 0x0f0f,
0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f00, 0x0fc0, 0x0ff0,
0x0f3c, 0x0f0f, 0x3fff, 0x0f00, 0x0f00, 0x3fc0, 0x0000, 0x0000,
0x0000, 0x0000, 0x0fff, 0x000f, 0x000f, 0x000f, 0x03ff, 0x0f00,
0x0f00, 0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0,
0x003c, 0x000f, 0x000f, 0x03ff, 0x0f0f, 0x0f0f, 0x0f0f, 0x03fc,
0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0x3c0f, 0x3c0f, 0x3c00,
0x0f00, 0x03c0, 0x00f0, 0x00f0, 0x00f0, 0x0000, 0x0000, 0x0000,
0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f3f, 0x03fc, 0x0fcf, 0x0f0f,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f,
0x0f0f, 0x0f0f, 0x0ffc, 0x03c0, 0x03c0, 0x00f0, 0x00fc, 0x0000,
0x0000, 0x0000, 0x0000, 0x00f0, 0x03fc, 0x0f0f, 0x0f0f, 0x0f0f,
0x0fff, 0x0f0f, 0x0f0f, 0x0f0f, 0x0000, 0x0000, 0x0000, 0x0000,
0x0fff, 0x3c3c, 0x3c3c, 0x3c3c, 0x0ffc, 0x3c3c, 0x3c3c, 0x3c3c,
0x0fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0ff0, 0x3c3c, 0x3c0f,
0x000f, 0x000f, 0x000f, 0x3c0f, 0x3c3c, 0x0ff0, 0x0000, 0x0000,
0x0000, 0x0000, 0x03ff, 0x0f3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
0x3c3c, 0x0f3c, 0x03ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fff,
0x303c, 0x003c, 0x0c3c, 0x0ffc, 0x0c3c, 0x003c, 0x303c, 0x3fff,
0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0x3c3c, 0x303c, 0x0c3c,
0x0ffc, 0x0c3c, 0x003c, 0x003c, 0x00ff, 0x0000, 0x0000, 0x0000,
0x0000, 0x0ff0, 0x3c3c, 0x3c0f, 0x000f, 0x000f, 0x3f0f, 0x3c0f,
0x3c3c, 0x3ff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f,
0x0f0f, 0x0f0f, 0x0fff, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0000,
0x0000, 0x0000, 0x0000, 0x03fc, 0x00f0, 0x00f0, 0x00f0, 0x00f0,
0x00f0, 0x00f0, 0x00f0, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000,
0x3fc0, 0x0f00, 0x0f00, 0x0f00, 0x0f00, 0x0f0f, 0x0f0f, 0x0f0f,
0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c3f, 0x3c3c, 0x0f3c,
0x0f3c, 0x03fc, 0x0f3c, 0x0f3c, 0x3c3c, 0x3c3f, 0x0000, 0x0000,
0x0000, 0x0000, 0x00ff, 0x003c, 0x003c, 0x003c, 0x003c, 0x303c,
0x3c3c, 0x3c3c, 0x3fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c0f,
0x3f3f, 0x3fff, 0x3fff, 0x3ccf, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
0x0000, 0x0000, 0x0000, 0x0000, 0x3c0f, 0x3c0f, 0x3c3f, 0x3cff,
0x3fff, 0x3fcf, 0x3f0f, 0x3c0f, 0x3c0f, 0x0000, 0x0000, 0x0000,
0x0000, 0x03f0, 0x0f3c, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
0x0f3c, 0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0fff, 0x3c3c,
0x3c3c, 0x3c3c, 0x0ffc, 0x003c, 0x003c, 0x003c, 0x00ff, 0x0000,
0x0000, 0x0000, 0x0000, 0x03f0, 0x0f3c, 0x3c0f, 0x3c0f, 0x3c0f,
0x3f0f, 0x3fcf, 0x0ffc, 0x0f00, 0x3fc0, 0x0000, 0x0000, 0x0000,
0x0fff, 0x3c3c, 0x3c3c, 0x3c3c, 0x0ffc, 0x0f3c, 0x3c3c, 0x3c3c,
0x3c3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f, 0x0f0f,
0x000f, 0x00fc, 0x03c0, 0x0f0f, 0x0f0f, 0x03fc, 0x0000, 0x0000,
0x0000, 0x0000, 0x0fff, 0x0cf3, 0x00f0, 0x00f0, 0x00f0, 0x00f0,
0x00f0, 0x00f0, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f,
0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x03fc,
0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
0x0f0f, 0x0f0f, 0x0f0f, 0x03fc, 0x00f0, 0x0000, 0x0000, 0x0000,
0x0000, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3ccf, 0x3ccf, 0x0f3c,
0x0f3c, 0x0f3c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f,
0x0f0f, 0x03fc, 0x00f0, 0x03fc, 0x0f0f, 0x0f0f, 0x0f0f, 0x0000,
0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x03fc,
0x00f0, 0x00f0, 0x00f0, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000,
0x3fff, 0x3f0f, 0x03c3, 0x03c0, 0x00f0, 0x003c, 0x303c, 0x3c0f,
0x3fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x03fc, 0x0f00, 0x0ffc, 0x0f0f, 0x0f0f, 0x3cfc, 0x0000, 0x0000,
0x0000, 0x0000, 0x003f, 0x003c, 0x003c, 0x0ffc, 0x3c3c, 0x3c3c,
0x3c3c, 0x3c3c, 0x0fcf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x03fc, 0x0f0f, 0x000f, 0x000f, 0x0f0f, 0x03fc,
0x0000, 0x0000, 0x0000, 0x0000, 0x0fc0, 0x0f00, 0x0f00, 0x0ffc,
0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x3cfc, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f, 0x0fff, 0x000f,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0f3c,
0x003c, 0x003c, 0x03ff, 0x003c, 0x003c, 0x003c, 0x00ff, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3cfc, 0x0f0f,
0x0f0f, 0x0f0f, 0x0ffc, 0x0f00, 0x0f0f, 0x03fc, 0x0000, 0x0000,
0x003f, 0x003c, 0x003c, 0x0f3c, 0x3cfc, 0x3c3c, 0x3c3c, 0x3c3c,
0x3c3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x03c0, 0x03c0, 0x0000,
0x03fc, 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x3ffc, 0x0000, 0x0000,
0x0000, 0x0000, 0x0f00, 0x0f00, 0x0000, 0x0ff0, 0x0f00, 0x0f00,
0x0f00, 0x0f00, 0x0f0f, 0x0f0f, 0x03fc, 0x0000, 0x0000, 0x003f,
0x003c, 0x003c, 0x3c3c, 0x0f3c, 0x03fc, 0x0f3c, 0x3c3c, 0x3c3f,
0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x03c0, 0x03c0, 0x03c0,
0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x3ffc, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0fff, 0x3ccf, 0x3ccf, 0x3ccf,
0x3ccf, 0x3c0f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x03ff, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f,
0x0f0f, 0x0f0f, 0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0fcf, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
0x0ffc, 0x003c, 0x00ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x3cfc, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0ffc, 0x0f00, 0x3fc0,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f3f, 0x3f3c, 0x3cfc,
0x003c, 0x003c, 0x00ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x03fc, 0x0f0f, 0x003c, 0x03c0, 0x0f0f, 0x03fc,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0030, 0x003c, 0x0fff,
0x003c, 0x003c, 0x003c, 0x0f3c, 0x03f0, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
0x0f0f, 0x3cfc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x03fc, 0x00f0, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c0f, 0x3c0f,
0x3ccf, 0x3ccf, 0x0f3c, 0x0f3c, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x3c0f, 0x0f3c, 0x03f0, 0x03f0, 0x0f3c,
0x3c0f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x0ff0, 0x0f00, 0x03c0, 0x00ff,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0fff, 0x0f03, 0x03c0,
0x003c, 0x0c0f, 0x0fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x03fc,
0x0f0f, 0x0f00, 0x03c0, 0x00f0, 0x00f0, 0x0000, 0x00f0, 0x00f0,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0f00, 0x03c0, 0x00f0, 0x003c, 0x003c, 0x003c, 0x00f0,
0x03c0, 0x0f00, 0x0000, 0x0000, 0x0000, 0x0000, 0x003c, 0x00f0,
0x03c0, 0x0f00, 0x0f00, 0x0f00, 0x03c0, 0x00f0, 0x003c, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x03f0, 0x0000,
0x0000, 0x03f0, 0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0,
0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x3ffc, 0x3ffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x03c0, 0x03c0, 0x3ffc, 0x3ffc,
0x03c0, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x3ffc, 0x0000, 0x0000, 0x3ffc, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f0f,
0x03fc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
//0---------------------------
0x0000, 0x0ffc, 0x3c0f, 0x3f0f, 0x3fcf, 0x3ccf, 0x3cff, 0x3c3f,
0x3c0f, 0x0ffc, 0x0000, 0x0000, 0x0000,
//1---------------------------
0x0000, 0x00c0, 0x00f0, 0x00ff, 0x00f0, 0x00f0, 0x00f0, 0x00f0,
0x00f0, 0x0fff, 0x0000, 0x0000, 0x0000,
//2---------------------------
0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f00, 0x03c0, 0x00f0, 0x003c,
0x0f0f, 0x0fff, 0x0000, 0x0000, 0x0000,
//3---------------------------
0x0000, 0x03fc, 0x0f0f, 0x0f00, 0x0f00, 0x03f0, 0x0f00, 0x0f00,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000,
//4---------------------------
0x0000, 0x0f00, 0x0fc0, 0x0ff0, 0x0f3c, 0x0f0f, 0x3fff, 0x0f00,
0x0f00, 0x3fc0, 0x0000, 0x0000, 0x0000,
//5---------------------------
0x0000, 0x0fff, 0x000f, 0x000f, 0x000f, 0x03ff, 0x0f00, 0x0f00,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000,
//6---------------------------
0x0000, 0x03f0, 0x003c, 0x000f, 0x000f, 0x03ff, 0x0f0f, 0x0f0f,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000,
//7---------------------------
0x0000, 0x3fff, 0x3c0f, 0x3c0f, 0x3c00, 0x0f00, 0x03c0, 0x00f0,
0x00f0, 0x00f0, 0x0000, 0x0000, 0x0000,
//8---------------------------
0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f3f, 0x03fc, 0x0fcf, 0x0f0f,
0x0f0f, 0x03fc, 0x0000, 0x0000, 0x0000,
//9---------------------------
0x0000, 0x03fc, 0x0f0f, 0x0f0f, 0x0f0f, 0x0ffc, 0x03c0, 0x03c0,
0x00f0, 0x00fc, 0x0000, 0x0000, 0x0000,
} ;

View File

@ -0,0 +1,16 @@
/*******************************************************************************
Filename: hal_lcd_fonts.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef __HAL_LCD_FONTS_H
#define __HAL_LCD_FONTS_H
#define FONT_HEIGHT 12 // Each character has 13 lines
#include <stdint.h>
extern const uint8_t fonts_lookup[];
extern const uint16_t fonts[];
#endif // __HAL_LCD_FONTS_H

View File

@ -0,0 +1,86 @@
/*
* 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.
*
*/
/*
* hal_tick.c
*
* Implementation for MSP430 Experimenter board using 250 ms ticks provided by Timer A1
*
*/
#include <msp430x54x.h>
#include <stdlib.h>
#include "hal_compat.h"
#include <btstack/hal_tick.h>
static void dummy_handler(void){};
static void (*tick_handler)(void) = &dummy_handler;
// Auxillary Clock (ACLK) = 32768 hz
// 8192 ticks = 1/4 second
#define TIMER_COUNTDOWN 8192
void hal_tick_init(void){
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CTL = TASSEL_1 | MC_2 | TACLR; // use ACLK (32768), contmode, clear TAR
TA1CCR0 = TIMER_COUNTDOWN; // -> 1/4 s
}
void hal_tick_set_handler(void (*handler)(void)){
if (handler == NULL){
tick_handler = &dummy_handler;
return;
}
tick_handler = handler;
}
int hal_tick_get_tick_period_in_ms(void){
return 250;
}
// Timer A1 interrupt service routine
#ifdef __GNUC__
__attribute__((interrupt(TIMER1_A0_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=TIMER1_A0_VECTOR
__interrupt
#endif
void timerA0ISR(void){
TA1CCR0 += TIMER_COUNTDOWN;
(*tick_handler)();
// force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
}

View File

@ -0,0 +1,326 @@
/**
* @file hal_bt.c
***************************************************************************/
#include <stdint.h>
#include <msp430x54x.h>
#include "hal_compat.h"
#include <btstack/hal_uart_dma.h>
extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
// debugging only
// #include <stdio.h>
#define BT_PORT_OUT P9OUT
#define BT_PORT_SEL P9SEL
#define BT_PORT_DIR P9DIR
#define BT_PORT_REN P9REN
#define BT_PIN_TXD BIT4
#define BT_PIN_RXD BIT5
// RXD P9.5
// TXD P9.4
// RTS P1.4
// CTS P1.3
void dummy_handler(void){};
// rx state
static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0;
// tx state
static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0;
// handlers
static void (*rx_done_handler)(void) = dummy_handler;
static void (*tx_done_handler)(void) = dummy_handler;
static void (*cts_irq_handler)(void) = dummy_handler;
/**
* @brief Initializes the serial communications peripheral and GPIO ports
* to communicate with the PAN BT .. assuming 16 Mhz CPU
*
* @param none
*
* @return none
*/
void hal_uart_dma_init(void)
{
BT_PORT_SEL |= BT_PIN_RXD + BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR &= ~BT_PIN_RXD;
// set BT RTS (P1.4)
P1SEL &= ~BIT4; // = 0 - I/O
P1DIR |= BIT4; // = 1 - Output
P1OUT |= BIT4; // = 1 - RTS high -> stop
// set BT CTS
P1SEL &= ~BIT3; // = 0 - I/O
P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS
// set BT SHUTDOWN (P8.2) to 1 (active low)
P8SEL &= ~BIT2; // = 0 - I/O
P8DIR |= BIT2; // = 1 - Output
P8OUT |= BIT2; // = 1 - Active low -> ok
// Enable ACLK to provide 32 kHz clock to Bluetooth module
P11SEL |= BIT0;
P11DIR |= BIT0;
// wait for Bluetooth to power up properly after providing 32khz clock
waitAboutOneSecond();
UCA2CTL1 |= UCSWRST; //Reset State
UCA2CTL0 = UCMODE_0;
UCA2CTL0 &= ~UC7BIT; // 8bit char
UCA2CTL1 |= UCSSEL_2;
UCA2CTL1 &= ~UCSWRST; // continue
hal_uart_dma_set_baud(115200);
}
/**
UART used in low-frequency mode
In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
16000000 / 576000 = 277.77
16000000 / 115200 = 138.88
16000000 / 921600 = 17.36
16000000 / 1000000 = 16.00
16000000 / 2000000 = 8.00
16000000 / 2400000 = 6.66
16000000 / 3000000 = 3.33
16000000 / 4000000 = 2.00
*/
int hal_uart_dma_set_baud(uint32_t baud){
int result = 0;
UCA2CTL1 |= UCSWRST; //Reset State
switch (baud){
case 4000000:
UCA2BR0 = 2;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 3000000:
UCA2BR0 = 3;
UCA2BR1 = 0;
UCA2MCTL= 3 << 1; // + 0.375
break;
case 2400000:
UCA2BR0 = 6;
UCA2BR1 = 0;
UCA2MCTL= 5 << 1; // + 0.625
break;
case 2000000:
UCA2BR0 = 8;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 1000000:
UCA2BR0 = 16;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 921600:
UCA2BR0 = 17;
UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375
break;
case 115200:
UCA2BR0 = 138; // from family user guide
UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // + 0.875
break;
case 57600:
UCA2BR0 = 21;
UCA2BR1 = 1;
UCA2MCTL= 7 << 1; // + 0.875
break;
default:
result = -1;
break;
}
UCA2CTL1 &= ~UCSWRST; // continue
return result;
}
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
rx_done_handler = the_block_handler;
}
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
tx_done_handler = the_block_handler;
}
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
if (the_irq_handler){
P1IFG = 0; // no IRQ pending
P1IV = 0; // no IRQ pending
P1IES &= ~BIT3; // IRQ on 0->1 transition
P1IE |= BIT3; // enable IRQ for P1.3
cts_irq_handler = the_irq_handler;
return;
}
P1IE &= ~BIT3;
cts_irq_handler = dummy_handler;
}
/**********************************************************************/
/**
* @brief Disables the serial communications peripheral and clears the GPIO
* settings used to communicate with the BT.
*
* @param none
*
* @return none
**************************************************************************/
void hal_uart_dma_shutdown(void) {
UCA2IE &= ~(UCRXIE | UCTXIE);
UCA2CTL1 = UCSWRST; //Reset State
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_RXD;
BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
}
void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){
// printf("hal_uart_dma_send_block, size %u\n\r", len);
UCA2IE &= ~UCTXIE ; // disable TX interrupts
tx_buffer_ptr = (uint8_t *) data;
bytes_to_write = len;
UCA2IE |= UCTXIE; // enable TX interrupts
}
static inline void hal_uart_dma_enable_rx(void){
P1OUT &= ~BIT4; // = 0 - RTS low -> ok
}
static inline void hal_uart_dma_disable_rx(void){
P1OUT |= BIT4; // = 1 - RTS high -> stop
}
// int used to indicate a request for more new data
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
UCA2IE &= ~UCRXIE ; // disable RX interrupts
rx_buffer_ptr = buffer;
bytes_to_read = len;
UCA2IE |= UCRXIE; // enable RX interrupts
hal_uart_dma_enable_rx(); // enable receive
}
void hal_uart_dma_set_sleep(uint8_t sleep){
hal_cpu_set_uart_needed_during_sleep(!sleep);
}
// block-wise "DMA" RX/TX UART driver
#ifdef __GNUC__
__attribute__((interrupt(USCI_A2_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=USCI_A2_VECTOR
__interrupt
#endif
void usbRxTxISR(void){
// find reason
switch (UCA2IV){
case 2: // RXIFG
if (bytes_to_read == 0) {
hal_uart_dma_disable_rx();
UCA2IE &= ~UCRXIE ; // disable RX interrupts
return;
}
*rx_buffer_ptr = UCA2RXBUF;
++rx_buffer_ptr;
--bytes_to_read;
if (bytes_to_read > 0) {
return;
}
P1OUT |= BIT4; // = 1 - RTS high -> stop
UCA2IE &= ~UCRXIE ; // disable RX interrupts
(*rx_done_handler)();
// force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break;
case 4: // TXIFG
if (bytes_to_write == 0){
UCA2IE &= ~UCTXIE ; // disable TX interrupts
return;
}
UCA2TXBUF = *tx_buffer_ptr;
++tx_buffer_ptr;
--bytes_to_write;
if (bytes_to_write > 0) {
return;
}
UCA2IE &= ~UCTXIE ; // disable TX interrupts
(*tx_done_handler)();
// force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break;
default:
break;
}
}
// CTS ISR
extern void ehcill_handle(uint8_t action);
#define EHCILL_CTS_SIGNAL 0x034
#ifdef __GNUC__
__attribute__((interrupt(PORT1_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=PORT1_VECTOR
__interrupt
#endif
void ctsISR(void){
P1IV = 0;
(*cts_irq_handler)();
}

View File

@ -0,0 +1,116 @@
/**
* @file hal_usb.c
*
* Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#include <msp430x54x.h>
#include "hal_usb.h"
#ifdef USE_IRQ_RX
static char halUsbReceiveBuffer[255];
static unsigned char bufferSize=0;
#endif
/************************************************************************
* @brief Initializes the serial communications peripheral and GPIO ports
* to communicate with the TUSB3410.
*
* @param none
*
* @return none
**************************************************************************/
void halUsbInit(void)
{
#ifdef USE_IRQ_RX
volatile unsigned char i;
for (i = 0;i < 255; i++){
halUsbReceiveBuffer[i]='\0';
}
bufferSize = 0;
#endif
USB_PORT_SEL |= USB_PIN_RXD + USB_PIN_TXD;
USB_PORT_DIR |= USB_PIN_TXD;
USB_PORT_DIR &= ~USB_PIN_RXD;
UCA1CTL1 |= UCSWRST; //Reset State
UCA1CTL0 = UCMODE_0;
UCA1CTL0 &= ~UC7BIT; // 8bit char
UCA1CTL1 |= UCSSEL_2;
UCA1BR0 = 16; // 8Mhz/57600=138
UCA1BR1 = 1;
UCA1MCTL = 0xE;
UCA1CTL1 &= ~UCSWRST;
// UCA1IE |= UCRXIE;
// __bis_SR_register(GIE); // Enable Interrupts
}
/************************************************************************
* @brief Disables the serial communications peripheral and clears the GPIO
* settings used to communicate with the TUSB3410.
*
* @param none
*
* @return none
**************************************************************************/
void halUsbShutDown(void)
{
UCA1IE &= ~UCRXIE;
UCA1CTL1 = UCSWRST; //Reset State
USB_PORT_SEL &= ~( USB_PIN_RXD + USB_PIN_TXD );
USB_PORT_DIR |= USB_PIN_TXD;
USB_PORT_DIR |= USB_PIN_RXD;
USB_PORT_OUT &= ~(USB_PIN_TXD + USB_PIN_RXD);
}
/************************************************************************
* @brief Sends a character over UART to the TUSB3410.
*
* @param character The character to be sent.
*
* @return none
**************************************************************************/
void halUsbSendChar(char character)
{
while (!(UCA1IFG & UCTXIFG));
UCA1TXBUF = character;
}
char halUsbRecvChar(){
while (!(UCA1IFG & UCRXIFG));
return UCA1RXBUF;
}
/************************************************************************
* @brief Sends a string of characters to the TUSB3410
*
* @param string[] The array of characters to be transmit to the TUSB3410.
*
* @param length The length of the string.
*
* @return none
**************************************************************************/
void halUsbSendString(char string[], unsigned char length)
{
volatile unsigned char i;
for (i=0; i < length; i++)
halUsbSendChar(string[i]);
}
#ifdef USE_IRQ_RX
/************************************************************************/
interrupt(USCI_A1_VECTOR) USCI_A1_ISR (void)
{
halUsbReceiveBuffer[bufferSize++] = UCA1RXBUF;
__bic_SR_register_on_exit(LPM3_bits);
}
#endif
// provide putchar used by printf
int putchar(int c){
halUsbSendChar(c);
return 1;
}

View File

@ -0,0 +1,26 @@
/*******************************************************************************
@file hal_usb.h
Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#ifndef HAL_USB_H
#define HAL_USB_H
#define USB_PORT_OUT P5OUT
#define USB_PORT_SEL P5SEL
#define USB_PORT_DIR P5DIR
#define USB_PORT_REN P5REN
#define USB_PIN_TXD BIT6
#define USB_PIN_RXD BIT7
/*-------------------------------------------------------------
* Function Prototypes
* ------------------------------------------------------------*/
void halUsbInit(void);
void halUsbShutDown(void);
void halUsbSendChar(char character);
void halUsbSendString(char string[], unsigned char length);
char halUsbRecvChar();
#endif

View File

@ -0,0 +1,30 @@
/************************************************************************
* @brief Checks for the board revision and returns a value < 0 if wrong
* revision is specified in main.c
*
* @param none
*
* @return Whether or not the board revision matches the software
* - 0 - The board revision does not match the software
* - 1 - The board revision matches the software
*************************************************************************/
unsigned char assert_board_version( void )
{
P8DIR &= ~BIT7; // Set P8.7 input
P8OUT |= BIT7; // Set pullup resistor
P8REN |= BIT7; // Enable pull up resistors
#ifdef REV_02
if(!(P8IN & BIT7)) // Board rev = 0_02?
return 0;
#else
if((P8IN & BIT7)) // Board rev = 0_03?
return 0;
#endif
P8DIR |= BIT7; // Set P8.7 output
P8OUT &= ~BIT7; // Set P8.7 = 0
P8REN &= ~BIT7; // Disable pull up resistors
return 1;
}

View File

@ -0,0 +1,5 @@
#ifndef __HAL_UTIL_H
#define __HAL_UTIL_H
#endif // __HAL_UTIL_H

View File

@ -0,0 +1,357 @@
// *****************************************************************************
//
// keyboard_demo
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bt_control_cc256x.h"
#include "hal_adc.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_lcd.h"
#include "hal_usb.h"
#include "UserExperienceGraphics.h"
#include <msp430x54x.h>
#include <btstack/run_loop.h>
#include <btstack/hci_cmds.h>
#include "btstack_memory.h"
#include "hci.h"
#include "l2cap.h"
#define INQUIRY_INTERVAL 15
#define FONT_HEIGHT 12 // Each character has 13 lines
#define FONT_WIDTH 8
static int row = 0;
extern int dumpCmds;
const char *hexMap = "0123456789ABCDEF";
static char lineBuffer[20];
static uint8_t num_chars = 0;
static bd_addr_t keyboard;
static int haveKeyboard = 0;
typedef enum {
boot = 1,
inquiry,
w4_inquiry_cmd_complete,
w4_l2cap_hii_connect,
connected
} state_t;
static state_t state = 0;
#define KEYCODE_RETURN '\n'
#define KEYCODE_ESCAPE 27
#define KEYCODE_TAB '\t'
#define KEYCODE_BACKSPACE 0x7f
#define KEYCODE_ILLEGAL 0xffff
#define KEYCODE_CAPSLOCK KEYCODE_ILLEGAL
#define MOD_SHIFT 0x22
/**
* English (US)
*/
static uint16_t keytable_us_none [] = {
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 0-3 */
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', /* 4 - 13 */
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 14 - 23 */
'u', 'v', 'w', 'x', 'y', 'z', /* 24 - 29 */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', /* 30 - 39 */
KEYCODE_RETURN, KEYCODE_ESCAPE, KEYCODE_BACKSPACE, KEYCODE_TAB, ' ', /* 40 - 44 */
'-', '=', '[', ']', '\\', KEYCODE_ILLEGAL, ';', '\'', 0x60, ',', /* 45 - 54 */
'.', '/', KEYCODE_CAPSLOCK, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 55 - 60 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 61-64 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 65-68 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 69-72 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 73-76 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 77-80 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 81-84 */
'*', '-', '+', '\n', '1', '2', '3', '4', '5', /* 85-97 */
'6', '7', '8', '9', '0', '.', 0xa7, /* 97-100 */
};
static uint16_t keytable_us_shift[] = {
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 0-3 */
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 4 - 13 */
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 14 - 23 */
'U', 'V', 'W', 'X', 'Y', 'Z', /* 24 - 29 */
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', /* 30 - 39 */
KEYCODE_RETURN, KEYCODE_ESCAPE, KEYCODE_BACKSPACE, KEYCODE_TAB, ' ', /* 40 - 44 */
'_', '+', '{', '}', '|', KEYCODE_ILLEGAL, ':', '"', 0x7E, '<', /* 45 - 54 */
'>', '?', KEYCODE_CAPSLOCK, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 55 - 60 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 61-64 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 65-68 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 69-72 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 73-76 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 77-80 */
KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, KEYCODE_ILLEGAL, /* 81-84 */
'*', '-', '+', '\n', '1', '2', '3', '4', '5', /* 85-97 */
'6', '7', '8', '9', '0', '.', 0xb1, /* 97-100 */
};
// decode hid packet into buffer - return number of valid keys events
#define NUM_KEYS 6
uint8_t last_keyboard_state[NUM_KEYS];
uint16_t input[NUM_KEYS];
static char last_state_init = 0;
uint16_t last_key;
uint16_t last_mod;
uint16_t last_char;
uint8_t last_key_new;
void doLCD(void){
//Initialize LCD and backlight
// 138 x 110, 4-level grayscale pixels.
halLcdInit();
// halLcdBackLightInit();
// halLcdSetBackLight(0); // 8 for normal
halLcdSetContrast(100);
halLcdClearScreen();
halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 );
halLcdPrintLine("BTstack on ", 0, 0);
halLcdPrintLine("TI MSP430", 1, 0);
halLcdPrintLine("Keyboard", 2, 0);
halLcdPrintLine("Init...", 3, 0);
row = 4;
}
void clearLine(int line){
halLcdClearImage(130, FONT_HEIGHT, 0, line*FONT_HEIGHT);
}
void printLine(char *text){
printf("LCD: %s\n\r", text);
halLcdPrintLine(text, row++, 0);
}
// put 'lineBuffer' on screen
void showLine(void){
clearLine(row);
halLcdPrintLine(lineBuffer, row, 0);
printf("LCD: %s\n\r", lineBuffer);
}
unsigned char hid_process_packet(unsigned char *hid_report, uint16_t *buffer, uint8_t max_keys){
// check for key report
if (hid_report[0] != 0xa1 || hid_report[1] != 0x01) {
return 0;
}
u_char modifier = hid_report[2];
u_char result = 0;
u_char i;
u_char j;
if (!last_state_init)
{
for (i=0;i<NUM_KEYS;i++){
last_keyboard_state[i] = 0;
}
last_state_init = 1;
}
for (i=0; i< NUM_KEYS && result < max_keys; i++){
// find key in last state
uint8_t new_event = hid_report[4+i];
if (new_event){
for (j=0; j<NUM_KEYS; j++){
if (new_event == last_keyboard_state[j]){
new_event = 0;
break;
}
}
if (!new_event) continue;
buffer[result++] = new_event;
last_key = new_event;
last_mod = modifier;
}
}
// store keyboard state
for (i=0;i<NUM_KEYS;i++){
last_keyboard_state[i] = hid_report[4+i];
}
return result;
}
static void l2cap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type == HCI_EVENT_PACKET && packet[0] == L2CAP_EVENT_CHANNEL_OPENED){
if (packet[2]) {
printf("Connection failed\n\r");
return;
}
printf("Connected\n\r");
num_chars = 0;
lineBuffer[num_chars++] = 'T';
lineBuffer[num_chars++] = 'y';
lineBuffer[num_chars++] = 'p';
lineBuffer[num_chars++] = 'e';
lineBuffer[num_chars++] = ' ';
lineBuffer[num_chars] = 0;
showLine();
}
if (packet_type == L2CAP_DATA_PACKET){
// handle input
// printf("HID report, size %u\n\r", size);
uint8_t count = hid_process_packet(packet, (uint16_t *) &input[0], NUM_KEYS);
if (!count) return;
uint8_t new_char;
// handle shift
if (last_mod & MOD_SHIFT) {
new_char = keytable_us_shift[input[0]];
} else {
new_char = keytable_us_none[input[0]];
}
// add to buffer
if (new_char == KEYCODE_BACKSPACE){
if (num_chars <= 5) return;
--num_chars;
lineBuffer[num_chars] = 0;
showLine();
return;
}
// 17 chars fit into one line
lineBuffer[num_chars] = new_char;
lineBuffer[num_chars+1] = 0;
if(num_chars < 16) num_chars++;
showLine();
}
}
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
int i,j;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
printLine("Inquiry");
state = inquiry;
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
break;
}
break;
case HCI_EVENT_INQUIRY_RESULT:
// ignore further results
if (haveKeyboard) break;
// ignore none keyboards
if ((packet[12] & 0x40) != 0x40 || packet[13] != 0x25) break;
// flip addr
bt_flip_addr(keyboard, &packet[3]);
// show
printf("Keyboard:\n\r");
// addr
j=0;
for (i=0;i<6;i++){
lineBuffer[j++] = hexMap[ keyboard[i] >> 4 ];
lineBuffer[j++] = hexMap[ keyboard[i] & 0x0f ];
if (i<5) lineBuffer[j++] = ':';
}
lineBuffer[j++] = 0;
printLine(lineBuffer);
haveKeyboard = 1;
hci_send_cmd(&hci_inquiry_cancel);
state = w4_inquiry_cmd_complete;
break;
case HCI_EVENT_INQUIRY_COMPLETE:
printLine("No keyboard found :(");
break;
case HCI_EVENT_LINK_KEY_REQUEST:
// deny link key request
hci_send_cmd(&hci_link_key_request_negative_reply, &keyboard);
break;
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printLine( "Enter 0000");
hci_send_cmd(&hci_pin_code_request_reply, &keyboard, 4, "0000");
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel) ) {
// inq successfully cancelled
// printLine("Connecting");
l2cap_create_channel_internal(NULL, l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
break;
}
}
}
}
int main(void){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// Debug UART
halUsbInit();
// show off
doLCD();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
/// GET STARTED ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
return 0;
}

View File

@ -0,0 +1,94 @@
// *****************************************************************************
//
// led_counter demo - uses the BTstack run loop to blink an LED
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include "btstack_memory.h"
#include <btstack/run_loop.h>
#include "btstack-config.h"
#define HEARTBEAT_PERIOD_MS 1000
static int counter = 0;
static timer_source_t heartbeat;
static void run_loop_register_timer(timer_source_t *timer, uint16_t period){
run_loop_set_timer(timer, period);
run_loop_add_timer(timer);
}
static void heartbeat_handler(timer_source_t *ts){
// increment counter
char lineBuffer[30];
sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter);
printf(lineBuffer);
// toggle LED
LED_PORT_OUT = LED_PORT_OUT ^ LED_2;
// re-register timer
run_loop_register_timer(ts, HEARTBEAT_PERIOD_MS);
}
static void timer_setup(){
// set one-shot timer
heartbeat.process = &heartbeat_handler;
run_loop_register_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
}
static void hw_setup(){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
}
static void btstack_setup(){
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
}
// main
int main(void)
{
hw_setup();
btstack_setup();
timer_setup();
printf("Run...\n\r");
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,11 @@
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "BTstack"
CHARACTERISTIC, GAP_APPEARANCE, READ, 00 00
PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
PRIMARY_SERVICE, FFF0
CHARACTERISTIC, FFF1, READ | WRITE | DYNAMIC,
CHARACTERISTIC, FFF2, READ | WRITE | DYNAMIC,
CHARACTERISTIC, 00001234-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC,

View File

@ -0,0 +1,151 @@
// *****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
// *****************************************************************************
#include "btstack-config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "sdp_parser.h"
#include "sdp_client.h"
#include "sdp_query_util.h"
#include "bt_control_cc256x.h"
#include "hal_adc.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_lcd.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include "hci.h"
#include "btstack_memory.h"
#include "hci_dump.h"
#include "l2cap.h"
static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
static const uint8_t des_attributeIDList[] = {0x35, 0x05, 0x0A, 0x00, 0x01, 0xff, 0xff}; // Arribute: 0x0001 - 0xffff
static const uint8_t des_serviceSearchPattern[] = {0x35, 0x03, 0x19, 0x00, 0x00};
uint16_t attribute_id = -1;
uint16_t record_id = -1;
int attribute_value_buffer_size = 1000;
uint8_t attribute_value[1000];
static void handle_general_sdp_parser_event(sdp_query_event_t * event);
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
uint8_t event = packet[0];
switch (event) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started
if (packet[2] == HCI_STATE_WORKING){
sdp_general_query_for_uuid(remote, 0x1002);
}
break;
default:
break;
}
}
static void assertBuffer(int size){
if (size > attribute_value_buffer_size){
printf("Buffer size exceeded: available %d, required %d", attribute_value_buffer_size, size);
}
}
static void handle_general_sdp_parser_event(sdp_query_event_t * event){
sdp_query_attribute_value_event_t * ve;
sdp_query_complete_event_t * ce;
switch (event->type){
case SDP_QUERY_ATTRIBUTE_VALUE:
ve = (sdp_query_attribute_value_event_t*) event;
// handle new record
if (ve->record_id != record_id){
record_id = ve->record_id;
printf("\n---\nRecord nr. %u\n", record_id);
}
assertBuffer(ve->attribute_length);
attribute_value[ve->data_offset] = ve->data;
if ((uint16_t)(ve->data_offset+1) == ve->attribute_length){
printf("Attribute 0x%04x: ", ve->attribute_id);
de_dump_data_element(attribute_value);
}
break;
case SDP_QUERY_COMPLETE:
ce = (sdp_query_complete_event_t*) event;
printf("General query done with status %d.\n\n", ce->status);
break;
}
}
static void hw_setup(){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
// ready - enable irq used in h4 task
__enable_interrupt();
}
static void btstack_setup(){
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
}
int main(void){
sdp_parser_init();
sdp_parser_register_callback(handle_general_sdp_parser_event);
hw_setup();
btstack_setup();
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
return 0;
}

View File

@ -0,0 +1,148 @@
// *****************************************************************************
//
// minimal setup for SDP client over USB or UART
//
// *****************************************************************************
#include "btstack-config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "sdp_query_rfcomm.h"
#include "bt_control_cc256x.h"
#include "hal_adc.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_lcd.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include "hci.h"
#include "btstack_memory.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "bt_control_cc256x.h"
static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
static uint8_t service_index = 0;
static uint8_t channel_nr[10];
static char* service_name[10];
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
uint8_t event = packet[0];
switch (event) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started
if (packet[2] == HCI_STATE_WORKING){
sdp_query_rfcomm_channel_and_name_for_uuid(remote, 0x1002);
}
break;
default:
break;
}
}
void store_found_service(uint8_t * name, uint8_t port){
printf("APP: Service name: '%s', RFCOMM port %u\n", name, port);
channel_nr[service_index] = port;
service_name[service_index] = (char*) malloc(SDP_SERVICE_NAME_LEN+1);
strncpy(service_name[service_index], (char*) name, SDP_SERVICE_NAME_LEN);
service_name[service_index][SDP_SERVICE_NAME_LEN] = 0;
service_index++;
}
void report_found_services(){
printf("\n *** Client query response done. ");
if (service_index == 0){
printf("No service found.\n\n");
} else {
printf("Found following %d services:\n", service_index);
}
int i;
for (i=0; i<service_index; i++){
printf(" Service name %s, RFCOMM port %u\n", service_name[i], channel_nr[i]);
}
printf(" ***\n\n");
}
void handle_query_rfcomm_event(sdp_query_event_t * event, void * context){
sdp_query_rfcomm_service_event_t * ve;
switch (event->type){
case SDP_QUERY_RFCOMM_SERVICE:
ve = (sdp_query_rfcomm_service_event_t*) event;
store_found_service(ve->service_name, ve->channel_nr);
break;
case SDP_QUERY_COMPLETE:
report_found_services();
break;
}
}
static void hw_setup(){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
// ready - enable irq used in h4 task
__enable_interrupt();
}
static void btstack_setup(){
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
}
int main(void){
sdp_query_rfcomm_register_callback(handle_query_rfcomm_event, NULL);
hw_setup();
btstack_setup();
printf("Run...\n\r");
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
return 0;
}

View File

@ -0,0 +1,249 @@
// *****************************************************************************
//
// accel_demo
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_adc.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include <btstack/sdp_util.h>
#include "hci.h"
#include "l2cap.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "rfcomm.h"
#include "sdp.h"
#include "btstack-config.h"
#define HEARTBEAT_PERIOD_MS 1000
#define FONT_HEIGHT 12 // Each character has 13 lines
#define FONT_WIDTH 8
static int row = 0;
char lineBuffer[80];
static uint8_t rfcomm_channel_nr = 1;
static uint16_t rfcomm_channel_id;
static uint8_t spp_service_buffer[150];
// SPP description
static uint8_t accel_buffer[6];
static void prepare_accel_packet(){
int16_t accl_x;
int16_t accl_y;
int16_t accl_z;
/* read the digital accelerometer x- direction and y - direction output */
halAccelerometerRead((int *)&accl_x, (int *)&accl_y, (int *)&accl_z);
accel_buffer[0] = 0x01; // Start of "header"
accel_buffer[1] = accl_x;
accel_buffer[2] = (accl_x >> 8);
accel_buffer[3] = accl_y;
accel_buffer[4] = (accl_y >> 8);
int index;
uint8_t checksum = 0;
for (index = 0; index < 5; index++) {
checksum += accel_buffer[index];
}
accel_buffer[5] = checksum;
/* start the ADC to read the next accelerometer output */
halAdcStartRead();
printf("Accel: X: %04d, Y: %04d, Z: %04d\n\r", accl_x, accl_y, accl_z);
}
static void send_packet(){
int err = rfcomm_send_internal(rfcomm_channel_id, (uint8_t *)accel_buffer, sizeof(accel_buffer));
switch(err){
case 0:
prepare_accel_packet();
break;
case BTSTACK_ACL_BUFFERS_FULL:
break;
default:
printf("rfcomm_send_internal() -> err %d\n\r", err);
break;
}
}
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
uint8_t rfcomm_channel_nr;
uint16_t mtu;
int err;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_local_name, "BTstack SPP Sensor");
}
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
bt_flip_addr(event_addr, &packet[6]);
printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
hci_discoverable_control(1);
break;
}
break;
case HCI_EVENT_LINK_KEY_REQUEST:
// deny link key request
printf("Link key request\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
break;
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printf("Pin code request - using '0000'\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
bt_flip_addr(event_addr, &packet[2]);
rfcomm_channel_nr = packet[8];
rfcomm_channel_id = READ_BT_16(packet, 9);
printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
rfcomm_accept_connection_internal(rfcomm_channel_id);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
if (packet[2]) {
printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
} else {
rfcomm_channel_id = READ_BT_16(packet, 12);
mtu = READ_BT_16(packet, 14);
printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
}
break;
case DAEMON_EVENT_HCI_PACKET_SENT:
case RFCOMM_EVENT_CREDITS:
if (rfcomm_can_send_packet_now(rfcomm_channel_id)) send_packet();
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
rfcomm_channel_id = 0;
break;
default:
break;
}
break;
default:
break;
}
}
// main
int main(void) {
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// Debug UART
halUsbInit();
// Accel
halAccelerometerInit();
// MindTree demo doesn't calibrate
// halAccelerometerCalibrate();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
prepare_accel_packet();
printf("Init BTstack...\n\r");
/// GET STARTED ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
// init RFCOMM
rfcomm_init();
rfcomm_register_packet_handler(packet_handler);
rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 100); // reserved channel, mtu=100
// init SDP, create record for SPP and register with SDP
sdp_init();
memset(spp_service_buffer, 0, sizeof(spp_service_buffer));
service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer;
sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Accel");
printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record)));
sdp_register_service_internal(NULL, service_record_item);
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
hci_power_control(HCI_POWER_ON);
// make discoverable
hci_discoverable_control(1);
// go!
run_loop_execute();
// happy compiler!
return 0;
}
/*
rfcomm_send_internal gets called before we have credits
rfcomm_send_internal returns undefined error codes???
*/

View File

@ -0,0 +1,236 @@
// *****************************************************************************
//
// spp_counter demo - it provides an SPP and sends a counter every second
//
// it doesn't use the LCD to get down to a minimal memory footprint
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include <btstack/sdp_util.h>
#include "hci.h"
#include "l2cap.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "rfcomm.h"
#include "sdp.h"
#include "btstack-config.h"
#define HEARTBEAT_PERIOD_MS 1000
static uint8_t rfcomm_channel_nr = 1;
static uint16_t rfcomm_channel_id;
static uint8_t spp_service_buffer[150];
static timer_source_t heartbeat;
static int real_counter = 0;
static int counter_to_send = 0;
enum STATE {INIT, W4_CONNECTION, W4_CHANNEL_COMPLETE, ACTIVE} ;
enum STATE state = INIT;
static void send_packet(void){
if (real_counter <= counter_to_send) return;
char lineBuffer[30];
sprintf(lineBuffer, "BTstack counter %04u\n\r", counter_to_send);
printf(lineBuffer);
int err = rfcomm_send_internal(rfcomm_channel_id, (uint8_t*) lineBuffer, strlen(lineBuffer));
switch (err){
case 0:
counter_to_send++;
break;
case BTSTACK_ACL_BUFFERS_FULL:
break;
default:
printf("rfcomm_send_internal() -> err %d\n\r", err);
break;
}
}
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
uint8_t rfcomm_channel_nr;
uint16_t mtu;
uint8_t event = packet[0];
// handle events, ignore data
if (packet_type != HCI_EVENT_PACKET) return;
switch (event) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter");
}
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
bt_flip_addr(event_addr, &packet[6]);
printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
hci_discoverable_control(1);
break;
}
break;
case HCI_EVENT_LINK_KEY_REQUEST:
// deny link key request
printf("Link key request\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
break;
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printf("Pin code request - using '0000'\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
bt_flip_addr(event_addr, &packet[2]);
rfcomm_channel_nr = packet[8];
rfcomm_channel_id = READ_BT_16(packet, 9);
printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
rfcomm_accept_connection_internal(rfcomm_channel_id);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
if (packet[2]) {
printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
} else {
rfcomm_channel_id = READ_BT_16(packet, 12);
mtu = READ_BT_16(packet, 14);
printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
}
break;
case DAEMON_EVENT_HCI_PACKET_SENT:
case RFCOMM_EVENT_CREDITS:
if (rfcomm_can_send_packet_now(rfcomm_channel_id)) send_packet();
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
rfcomm_channel_id = 0;
break;
default:
break;
}
}
static void run_loop_register_timer(timer_source_t *timer, uint16_t period){
run_loop_set_timer(timer, period);
run_loop_add_timer(timer);
}
static void timer_handler(timer_source_t *ts){
real_counter++;
// re-register timer
run_loop_register_timer(ts, HEARTBEAT_PERIOD_MS);
if (rfcomm_can_send_packet_now(rfcomm_channel_id)) send_packet();
}
static void timer_setup(){
// set one-shot timer
heartbeat.process = &timer_handler;
run_loop_register_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
}
static void hw_setup(){
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
// ready - enable irq used in h4 task
__enable_interrupt();
}
static void btstack_setup(){
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
// init RFCOMM
rfcomm_init();
rfcomm_register_packet_handler(packet_handler);
rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 100); // reserved channel, mtu=100
// init SDP, create record for SPP and register with SDP
sdp_init();
memset(spp_service_buffer, 0, sizeof(spp_service_buffer));
service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer;
sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter");
printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record)));
sdp_register_service_internal(NULL, service_record_item);
}
// main
int main(void){
hw_setup();
btstack_setup();
timer_setup();
printf("Run...\n\r");
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,204 @@
// *****************************************************************************
//
// spp_flowcontrol demo - it provides a SPP that use sincoming flow control
// Processing of data is simulated by granting the next
// credit only every second in the heartbeat handler
//
// it doesn't use the LCD to get down to a minimal memory footprint
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430x54x.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include <btstack/sdp_util.h>
#include "hci.h"
#include "l2cap.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "rfcomm.h"
#include "sdp.h"
#include "btstack-config.h"
#define HEARTBEAT_PERIOD_MS 500
static uint8_t rfcomm_channel_nr = 1;
static uint16_t rfcomm_channel_id;
static uint8_t rfcomm_send_credit = 0;
static uint8_t spp_service_buffer[150];
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
uint8_t rfcomm_channel_nr;
uint16_t mtu;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]) {
case BTSTACK_EVENT_STATE:
// bt stack activated, get started - set local name
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_local_name, "BTstack SPP Flow Control");
}
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
bt_flip_addr(event_addr, &packet[6]);
printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
break;
}
if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
hci_discoverable_control(1);
break;
}
break;
case HCI_EVENT_LINK_KEY_REQUEST:
// deny link key request
printf("Link key request\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
break;
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printf("Pin code request - using '0000'\n\r");
bt_flip_addr(event_addr, &packet[2]);
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
bt_flip_addr(event_addr, &packet[2]);
rfcomm_channel_nr = packet[8];
rfcomm_channel_id = READ_BT_16(packet, 9);
printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
rfcomm_accept_connection_internal(rfcomm_channel_id);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
if (packet[2]) {
printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
} else {
rfcomm_channel_id = READ_BT_16(packet, 12);
mtu = READ_BT_16(packet, 14);
printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
rfcomm_channel_id = 0;
break;
default:
break;
}
break;
case RFCOMM_DATA_PACKET:
// hack: truncate data (we know that the packet is at least on byte bigger
packet[size] = 0;
puts( (const char *) packet);
rfcomm_send_credit = 1;
default:
break;
}
}
static void heartbeat_handler(struct timer *ts){
if (rfcomm_send_credit){
rfcomm_grant_credits(rfcomm_channel_id, 1);
rfcomm_send_credit = 0;
}
run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
run_loop_add_timer(ts);
}
// main
int main(void)
{
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
//Initialize clock and peripherals
halBoardInit();
halBoardStartXT1();
halBoardSetSystemClock(SYSCLK_16MHZ);
// init debug UART
halUsbInit();
// init LEDs
LED_PORT_OUT |= LED_1 | LED_2;
LED_PORT_DIR |= LED_1 | LED_2;
/// GET STARTED with BTstack ///
btstack_memory_init();
run_loop_init(RUN_LOOP_EMBEDDED);
// init HCI
hci_transport_t * transport = hci_transport_h4_dma_instance();
bt_control_t * control = bt_control_cc256x_instance();
hci_uart_config_t * config = hci_uart_config_cc256x_instance();
remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
hci_init(transport, config, control, remote_db);
// use eHCILL
bt_control_cc256x_enable_ehcill(1);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
// init RFCOMM
rfcomm_init();
rfcomm_register_packet_handler(packet_handler);
rfcomm_register_service_with_initial_credits_internal(NULL, rfcomm_channel_nr, 100, 1); // reserved channel, mtu=100, 1 credit
// init SDP, create record for SPP and register with SDP
sdp_init();
memset(spp_service_buffer, 0, sizeof(spp_service_buffer));
service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer;
sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter");
printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record)));
sdp_register_service_internal(NULL, service_record_item);
// set one-shot timer
timer_source_t heartbeat;
heartbeat.process = &heartbeat_handler;
run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
run_loop_add_timer(&heartbeat);
puts("SPP FlowControl Demo: simulates processing on received data...\n\r");
// ready - enable irq used in h4 task
__enable_interrupt();
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
// happy compiler!
return 0;
}