added eZ430-RF2560 port

This commit is contained in:
matthias.ringwald 2012-01-14 20:39:59 +00:00
parent 28ca2b4607
commit 275f34570a
20 changed files with 2608 additions and 0 deletions

26
eZ430-RF2560/config.h Normal file
View File

@ -0,0 +1,26 @@
#define EMBEDDED
#define HAVE_INIT_SCRIPT
#define HAVE_BZERO
#define HAVE_TICK
#define HAVE_EHCILL
// #define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define HCI_ACL_PAYLOAD_SIZE 52
//
#define MAX_SPP_CONNECTIONS 1
#define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS
#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_DB_MEM_DEVICE_LINK_KEYS 2
#define MAX_NO_DB_MEM_DEVICE_NAMES 0
#define MAX_NO_DB_MEM_SERVICES 1

View File

@ -0,0 +1,77 @@
#
# Makefile for eZ430-RF2560
#
# mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki
#
BTSTACK_ROOT = ../..
MCU = msp430x5438
CC = msp430-gcc
CFLAGS = -mmcu=${MCU} -g -Os -Wall -I. -I../src -I../firmware -I${BTSTACK_ROOT} -I${BTSTACK_ROOT}/chipset-cc256x -I${BTSTACK_ROOT}/src -I${BTSTACK_ROOT}/include
LDFLAGS = -mmcu=${MCU}
CORE = \
../src/hal_tick.c \
../src/hal_cpu.c \
../firmware/hal_board.c \
../firmware/hal_compat.c \
../firmware/hal_usb.c \
${BTSTACK_ROOT}/src/btstack_memory.c \
${BTSTACK_ROOT}/src/linked_list.c \
${BTSTACK_ROOT}/src/memory_pool.c \
${BTSTACK_ROOT}/src/run_loop.c \
${BTSTACK_ROOT}/src/run_loop_embedded.c
COMMON = \
../src/hal_uart_dma.c \
${BTSTACK_ROOT}/chipset-cc256x/bt_control_cc256x.c \
${BTSTACK_ROOT}/chipset-cc256x/cc2560_init_script.c \
${BTSTACK_ROOT}/src/hci.c \
${BTSTACK_ROOT}/src/hci_cmds.c \
${BTSTACK_ROOT}/src/hci_dump.c \
${BTSTACK_ROOT}/src/hci_transport_h4_ehcill_dma.c \
${BTSTACK_ROOT}/src/l2cap.c \
${BTSTACK_ROOT}/src/l2cap_signaling.c \
${BTSTACK_ROOT}/src/remote_device_db_memory.c \
${BTSTACK_ROOT}/src/rfcomm.c \
${BTSTACK_ROOT}/src/sdp.c \
${BTSTACK_ROOT}/src/sdp_util.c \
${BTSTACK_ROOT}/src/utils.c \
CORE_OBJ = $(CORE:.c=.o)
COMMON_OBJ = $(COMMON:.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_flowcontrol.hex
# missing: spp_accel.hex
led_counter.out: ${CORE_OBJ} led_counter.o
${CC} $^ ${LDFLAGS} -o $@
spp_accel.out: ${CORE_OBJ} ${COMMON_OBJ} spp_accel.o ../firmware/hal_adc.o
echo "accelerometer code not adapted yet for eZ430-RF2560 target"
${CC} $^ ${LDFLAGS} -o $@
spp_counter.out: ${CORE_OBJ} ${COMMON_OBJ} spp_counter.o ../firmware/hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
spp_flowcontrol.out: ${CORE_OBJ} ${COMMON_OBJ} spp_flowcontrol.o ../firmware/hal_adc.o
${CC} $^ ${LDFLAGS} -o $@
clean:
rm -f $ *.o *.out *.hex ../driver/*.o ../../src/*.o ../src/*.o ../firmware/*.o ${BTSTACK_ROOT}/chipset-cc256x/*.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,26 @@
#define EMBEDDED
#define HAVE_INIT_SCRIPT
#define HAVE_BZERO
#define HAVE_TICK
#define HAVE_EHCILL
// #define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define HCI_ACL_PAYLOAD_SIZE 52
//
#define MAX_SPP_CONNECTIONS 1
#define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS
#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_DB_MEM_DEVICE_LINK_KEYS 2
#define MAX_NO_DB_MEM_DEVICE_NAMES 0
#define MAX_NO_DB_MEM_SERVICES 1

View File

@ -0,0 +1,80 @@
//*****************************************************************************
//
// 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 "config.h"
#define HEARTBEAT_PERIOD_MS 1000
static void heartbeat_handler(struct timer *ts){
// increment counter
static int counter = 0;
char lineBuffer[30];
sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter);
printf(lineBuffer);
// toggle LED
LED_PORT_OUT = LED_PORT_OUT ^ LED_2;
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);
// 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!
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,279 @@
//*****************************************************************************
//
// 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_lcd.h"
#include "hal_usb.h"
#include "UserExperienceGraphics.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 "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[100];
// LCD setup
void doLCD(void){
//Initialize LCD
// 138 x 110, 4-level grayscale pixels.
halLcdInit();
halLcdSetContrast(100);
halLcdClearScreen();
halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 );
halLcdPrintLine("BTstack on ", 0, 0);
halLcdPrintLine("TI MSP430", 1, 0);
halLcdPrintLine("SPP ACCEL", 2, 0);
halLcdPrintLine("Init...", 4, 0);
row = 5;
}
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);
}
// 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);
}
// 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, "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)){
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
printLine( "PIN = 0000");
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]);
printLine("Connection failed :(");
} 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_channel_id) break;
// try send
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;
}
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;
// show off
doLCD();
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);
// 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,202 @@
//*****************************************************************************
//
// spp_counter demo - it provides a SPP and sends a counter every second
//
// 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/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 "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[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;
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)){
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;
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);
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);
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -0,0 +1,201 @@
//*****************************************************************************
//
// spp_counter demo - it provides a SPP and sends a counter every second
//
// 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/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 "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[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;
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)){
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;
}

430
eZ430-RF2560/firmware/hal_adc.c Executable file
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);
}

83
eZ430-RF2560/firmware/hal_adc.h Executable file
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

369
eZ430-RF2560/firmware/hal_board.c Executable file
View File

@ -0,0 +1,369 @@
/**
* @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,23 @@
/**
* 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
#pragma once
#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);

124
eZ430-RF2560/firmware/hal_usb.c Executable file
View File

@ -0,0 +1,124 @@
/**
* @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;
UCA3CTL1 |= UCSWRST; //Reset State
UCA3CTL0 = UCMODE_0;
UCA3CTL0 &= ~UC7BIT; // 8bit char
UCA3CTL1 |= UCSSEL_2;
// 115200 on 16 Mhz
// UCA3BR0 = 16; // 8Mhz/57600=138
// UCA3BR1 = 1;
// UCA3MCTL = 0xE;
// 9600 on 16 Mhz - from family user guide
UCA3BR1 = 0x06;
UCA3BR0 = 0x82;
UCA3MCTL = 0xC;
UCA3CTL1 &= ~UCSWRST;
// UCA3IE |= 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)
{
UCA3IE &= ~UCRXIE;
UCA3CTL1 = 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 (!(UCA3IFG & UCTXIFG));
UCA3TXBUF = character;
}
char halUsbRecvChar(){
while (!(UCA3IFG & UCRXIFG));
return UCA3RXBUF;
}
/**********************************************************************//**
* @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++] = UCA3RXBUF;
__bic_SR_register_on_exit(LPM3_bits);
}
#endif
// provide putchar used by printf
int putchar(int c){
halUsbSendChar(c);
return 1;
}

26
eZ430-RF2560/firmware/hal_usb.h Executable file
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 P10OUT
#define USB_PORT_SEL P10SEL
#define USB_PORT_DIR P10DIR
#define USB_PORT_REN P10REN
#define USB_PIN_TXD BIT4
#define USB_PIN_RXD BIT5
/*-------------------------------------------------------------
* 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,3 @@
#pragma once

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;
}

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
}

326
eZ430-RF2560/src/hal_uart_dma.c Executable file
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.3)
P1SEL &= ~BIT3; // = 0 - I/O
P1DIR |= BIT3; // = 1 - Output
P1OUT |= BIT3; // = 1 - RTS high -> stop
// set BT CTS (P1.4)
P1SEL &= ~BIT4; // = 0 - I/O
P1DIR &= ~BIT4; // = 0 - Input P1DIR |= BIT4; // RTS
// set BT SHUTDOWN (P2.7) to 1 (active low)
P2SEL &= ~BIT7; // = 0 - I/O
P2DIR |= BIT7; // = 1 - Output
P2OUT |= BIT7; // = 1 - Active low -> ok
// Enable ACLK to provide 32 kHz clock to Bluetooth module
P2SEL |= BIT6;
P2DIR |= BIT6;
// 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 &= ~BIT4; // IRQ on 0->1 transition
P1IE |= BIT4; // enable IRQ for P1.3
cts_irq_handler = the_irq_handler;
return;
}
P1IE &= ~BIT4;
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 &= ~BIT3; // = 0 - RTS low -> ok
}
static inline void hal_uart_dma_disable_rx(void){
P1OUT |= BIT3; // = 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 |= BIT3; // = 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)();
}