diff --git a/eZ430-RF2560/config.h b/eZ430-RF2560/config.h new file mode 100644 index 000000000..2430bb7e0 --- /dev/null +++ b/eZ430-RF2560/config.h @@ -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 + diff --git a/eZ430-RF2560/example/Makefile b/eZ430-RF2560/example/Makefile new file mode 100644 index 000000000..e95b4c968 --- /dev/null +++ b/eZ430-RF2560/example/Makefile @@ -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 diff --git a/eZ430-RF2560/example/config.h b/eZ430-RF2560/example/config.h new file mode 100644 index 000000000..2430bb7e0 --- /dev/null +++ b/eZ430-RF2560/example/config.h @@ -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 + diff --git a/eZ430-RF2560/example/led_counter.c b/eZ430-RF2560/example/led_counter.c new file mode 100644 index 000000000..62bf1b491 --- /dev/null +++ b/eZ430-RF2560/example/led_counter.c @@ -0,0 +1,80 @@ +//***************************************************************************** +// +// led_counter demo - uses the BTstack run loop to blink an LED +// +//***************************************************************************** + +#include +#include +#include +#include + +#include + +#include "hal_board.h" +#include "hal_compat.h" +#include "hal_usb.h" + +#include "btstack_memory.h" + +#include +#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; +} + diff --git a/eZ430-RF2560/example/spp_accel.c b/eZ430-RF2560/example/spp_accel.c new file mode 100644 index 000000000..2af4fafdb --- /dev/null +++ b/eZ430-RF2560/example/spp_accel.c @@ -0,0 +1,279 @@ +//***************************************************************************** +// +// accel_demo +// +//***************************************************************************** + +#include +#include +#include +#include + +#include + +#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 +#include +#include + +#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??? + +*/ + diff --git a/eZ430-RF2560/example/spp_counter.c b/eZ430-RF2560/example/spp_counter.c new file mode 100644 index 000000000..d37de68fb --- /dev/null +++ b/eZ430-RF2560/example/spp_counter.c @@ -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 +#include +#include +#include + +#include + +#include "bt_control_cc256x.h" +#include "hal_board.h" +#include "hal_compat.h" +#include "hal_usb.h" + +#include +#include +#include + +#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; +} + diff --git a/eZ430-RF2560/example/spp_flowcontrol.c b/eZ430-RF2560/example/spp_flowcontrol.c new file mode 100644 index 000000000..1799bd07a --- /dev/null +++ b/eZ430-RF2560/example/spp_flowcontrol.c @@ -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 +#include +#include +#include + +#include + +#include "bt_control_cc256x.h" +#include "hal_board.h" +#include "hal_compat.h" +#include "hal_usb.h" + +#include +#include +#include + +#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; +} + diff --git a/eZ430-RF2560/firmware/hal_adc.c b/eZ430-RF2560/firmware/hal_adc.c new file mode 100755 index 000000000..09d2ccbb8 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_adc.c @@ -0,0 +1,430 @@ +/** + * @file hal_adc.c + * + * Copyright 2008 Texas Instruments, Inc. +***************************************************************************/ + +#include "hal_adc.h" + +#include +#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); +} diff --git a/eZ430-RF2560/firmware/hal_adc.h b/eZ430-RF2560/firmware/hal_adc.h new file mode 100755 index 000000000..c7a379e56 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_adc.h @@ -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 diff --git a/eZ430-RF2560/firmware/hal_board.c b/eZ430-RF2560/firmware/hal_board.c new file mode 100755 index 000000000..4df408e87 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_board.c @@ -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; +} diff --git a/eZ430-RF2560/firmware/hal_board.h b/eZ430-RF2560/firmware/hal_board.h new file mode 100755 index 000000000..32e88d7c4 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_board.h @@ -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 diff --git a/eZ430-RF2560/firmware/hal_compat.c b/eZ430-RF2560/firmware/hal_compat.c new file mode 100644 index 000000000..4cac83635 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_compat.c @@ -0,0 +1,45 @@ +/** + * various functions to deal with flaws and portability issues + * + * @author Matthias Ringwald + */ + +#include "hal_compat.h" +#include + +// __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 diff --git a/eZ430-RF2560/firmware/hal_compat.h b/eZ430-RF2560/firmware/hal_compat.h new file mode 100644 index 000000000..ca508f451 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_compat.h @@ -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 + +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); + + + diff --git a/eZ430-RF2560/firmware/hal_usb.c b/eZ430-RF2560/firmware/hal_usb.c new file mode 100755 index 000000000..fa259ffff --- /dev/null +++ b/eZ430-RF2560/firmware/hal_usb.c @@ -0,0 +1,124 @@ +/** + * @file hal_usb.c + * + * Copyright 2008 Texas Instruments, Inc. +***************************************************************************/ +#include +#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; +} \ No newline at end of file diff --git a/eZ430-RF2560/firmware/hal_usb.h b/eZ430-RF2560/firmware/hal_usb.h new file mode 100755 index 000000000..97c64a83c --- /dev/null +++ b/eZ430-RF2560/firmware/hal_usb.h @@ -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 diff --git a/eZ430-RF2560/firmware/hal_util.c b/eZ430-RF2560/firmware/hal_util.c new file mode 100644 index 000000000..a849de363 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_util.c @@ -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; +} diff --git a/eZ430-RF2560/firmware/hal_util.h b/eZ430-RF2560/firmware/hal_util.h new file mode 100644 index 000000000..96786d745 --- /dev/null +++ b/eZ430-RF2560/firmware/hal_util.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/eZ430-RF2560/src/hal_cpu.c b/eZ430-RF2560/src/hal_cpu.c new file mode 100644 index 000000000..3a13ce12f --- /dev/null +++ b/eZ430-RF2560/src/hal_cpu.c @@ -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 + +#include "hal_board.h" +#include "hal_compat.h" + +#include + +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; + +} + + diff --git a/eZ430-RF2560/src/hal_tick.c b/eZ430-RF2560/src/hal_tick.c new file mode 100644 index 000000000..becebf85d --- /dev/null +++ b/eZ430-RF2560/src/hal_tick.c @@ -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 +#include +#include "hal_compat.h" + +#include + +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 +} diff --git a/eZ430-RF2560/src/hal_uart_dma.c b/eZ430-RF2560/src/hal_uart_dma.c new file mode 100755 index 000000000..81792767f --- /dev/null +++ b/eZ430-RF2560/src/hal_uart_dma.c @@ -0,0 +1,326 @@ +/** + * @file hal_bt.c + ***************************************************************************/ +#include + +#include +#include "hal_compat.h" + +#include + +extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled); + +// debugging only +// #include + +#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)(); +}