X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fdrivers%2Fao_btm.c;h=04bf413890e349014f0448b12bbedfef892d1841;hp=44155ec142aa934863daa384500726f503a3af09;hb=0686a7b8aec524d81bda4c572549a3a068ce0eed;hpb=9513be7f9d3d0b0ec29f6487fa9dc8f1ac24d0de diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 44155ec1..04bf4138 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,14 +17,170 @@ */ #include "ao.h" +#ifdef AO_BTM_INT_PORT +#include +#endif + +#ifndef ao_serial_btm_getchar +#define ao_serial_btm_putchar ao_serial1_putchar +#define _ao_serial_btm_pollchar _ao_serial1_pollchar +#define _ao_serial_btm_sleep_for(timeout) ao_sleep_for((void *) &ao_serial1_rx_fifo, timeout) +#define ao_serial_btm_set_speed ao_serial1_set_speed +#define ao_serial_btm_drain ao_serial1_drain +#endif int8_t ao_btm_stdio; -__xdata uint8_t ao_btm_connected; +uint8_t ao_btm_connected; + +#define BT_DEBUG 1 + +#if BT_DEBUG +char ao_btm_buffer[256]; +uint16_t ao_btm_ptr; +char ao_btm_dir; + +static void +ao_btm_add_char(char c) +{ + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ + if (dir != ao_btm_dir) { + ao_btm_add_char(dir); + ao_btm_dir = dir; + } + ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ + ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ + ao_btm_log_char(c, '<'); +} + +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ + int i; + char c; + uint16_t r; + + for (i = 0; i < ao_btm_ptr; i++) { + c = ao_btm_buffer[i]; + if (c < ' ' && c != '\n') + printf("\\%03o", ((int) c) & 0xff); + else + putchar(ao_btm_buffer[i]); + } + putchar('\n'); + r = ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success && r) + ao_btm_ptr = 0; + ao_cmd_status = ao_cmd_success; +} + +static void +ao_btm_speed(void) +{ + switch (ao_cmd_decimal()) { + case 57600: + ao_serial_btm_set_speed(AO_SERIAL_SPEED_57600); + break; + case 19200: + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); + break; + default: + ao_cmd_status = ao_cmd_syntax_error; + break; + } +} + +static uint8_t ao_btm_enable; + +static void +ao_btm_do_echo(void) +{ + int c; + while (ao_btm_enable) { + ao_arch_block_interrupts(); + while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable) + _ao_serial_btm_sleep_for(0); + ao_arch_release_interrupts(); + if (c != AO_READ_AGAIN) { + putchar(c); + flush(); + } + } + ao_exit(); +} + +static struct ao_task ao_btm_echo_task; + +static void +ao_btm_send(void) +{ + int c; + ao_btm_enable = 1; + ao_add_task(&ao_btm_echo_task, ao_btm_do_echo, "btm-echo"); + while ((c = getchar()) != '~') { + ao_serial_btm_putchar(c); + } + ao_btm_enable = 0; + ao_wakeup((void *) &ao_serial_btm_rx_fifo); +} + +const struct ao_cmds ao_btm_cmds[] = { + { ao_btm_dump, "d\0Dump btm buffer." }, + { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, + { ao_btm_send, "S\0BTM interactive mode. ~ to exit." }, + { 0, NULL }, +}; + +#define ao_btm_log_init() ao_cmd_register(&ao_btm_cmds[0]) + +#else +#define ao_btm_log_in_char(c) +#define ao_btm_log_out_char(c) +#define ao_btm_log_init() +#endif #define AO_BTM_MAX_REPLY 16 -__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; +char ao_btm_reply[AO_BTM_MAX_REPLY]; -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; +/* + * Read one bluetooth character. + * Returns AO_READ_AGAIN if no character arrives within 10ms + */ + +static int +ao_btm_getchar(void) +{ + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) { + c = _ao_serial_btm_sleep_for(AO_MS_TO_TICKS(10)); + if (c) { + c = AO_READ_AGAIN; + break; + } + } + ao_arch_release_interrupts(); + return c; +} /* * Read a line of data from the serial port, truncating @@ -34,27 +191,18 @@ uint8_t ao_btm_get_line(void) { uint8_t ao_btm_reply_len = 0; - char c; - - for (;;) { - - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { - if (ao_btm_reply_len < sizeof (ao_btm_reply)) - ao_btm_reply[ao_btm_reply_len++] = c; - if (c == '\r' || c == '\n') - goto done; - } - for (c = 0; c < 10; c++) { - ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) - break; - } - if (c == 10) - goto done; + int c; + uint8_t l; + + while ((c = ao_btm_getchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (c == '\r' || c == '\n') + break; } -done: - for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) - ao_btm_reply[c++] = '\0'; + for (l = ao_btm_reply_len; l < sizeof (ao_btm_reply);) + ao_btm_reply[l++] = '\0'; return ao_btm_reply_len; } @@ -85,7 +233,8 @@ ao_btm_echo(uint8_t echo) void ao_btm_putchar(char c) { - ao_serial_putchar(c); + ao_btm_log_out_char(c); + ao_serial_btm_putchar(c); ao_delay(1); } @@ -108,18 +257,27 @@ ao_btm_wait_reply(void) } void -ao_btm_string(__code char *cmd) +ao_btm_string(const char *cmd) { char c; - while (c = *cmd++) + while ((c = *cmd++) != '\0') ao_btm_putchar(c); } uint8_t -ao_btm_cmd(__code char *cmd) +ao_btm_cmd(const char *cmd) { ao_btm_drain(); + +#ifdef AO_BTM_INT_PORT + /* Trust that AltosDroid will eventually disconnect and let us + * get things set up. The BTM module doesn't appear to listen + * for +++, so we have no way to force a disconnect. + */ + while (ao_btm_connected) + ao_sleep(&ao_btm_connected); +#endif ao_btm_string(cmd); return ao_btm_wait_reply(); } @@ -146,14 +304,60 @@ ao_btm_set_name(void) uint8_t ao_btm_try_speed(uint8_t speed) { - ao_serial_set_speed(speed); - ao_btm_drain(); + ao_serial_btm_set_speed(speed); + ao_serial_btm_drain(); (void) ao_btm_cmd("\rATE0\rATQ0\r"); if (ao_btm_cmd("AT\r") == 1) return 1; return 0; } +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#define BT_CC1111 1 +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#define BT_CC1111 1 +#endif + +void +ao_btm_check_link() +{ +#if BT_CC1111 + ao_arch_critical( + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } + ); +#else + ao_arch_block_interrupts(); + if (ao_gpio_get(AO_BTM_INT_PORT, AO_BTM_INT_PIN) == 0) { + ao_btm_connected = 1; + } else { + ao_btm_connected = 0; + } + ao_arch_release_interrupts(); +#endif +} + +struct ao_task ao_btm_task; + /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -161,15 +365,15 @@ ao_btm_try_speed(uint8_t speed) void ao_btm(void) { +#ifdef AO_BTM_INT_PORT + ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); +#endif + /* * Wait for the bluetooth device to boot */ ao_delay(AO_SEC_TO_TICKS(3)); -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see @@ -195,53 +399,28 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, + ao_btm_drain(); + + ao_btm_stdio = ao_add_stdio(_ao_serial_btm_pollchar, + ao_serial_btm_putchar, NULL); ao_btm_echo(0); + /* Check current pin state */ + ao_btm_check_link(); + for (;;) { while (!ao_btm_connected) ao_sleep(&ao_btm_connected); while (ao_btm_connected) { - ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); + ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(20)); ao_delay(AO_SEC_TO_TICKS(3)); } } } -__xdata struct ao_task ao_btm_task; - -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - -void -ao_btm_check_link() __critical -{ - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } -} +#if BT_CC1111 void ao_btm_isr(void) #if BT_LINK_ON_P1 @@ -257,13 +436,36 @@ ao_btm_isr(void) } BT_PIFG = 0; } +#endif + +#ifdef AO_BTM_INT_PORT +void +ao_btm_isr(void) +{ + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); +} +#endif void ao_btm_init (void) { ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); + +#ifdef AO_BTM_RESET_PORT + ao_enable_output(AO_BTM_RESET_PORT,AO_BTM_RESET_PIN,0); +#endif + +#ifdef AO_BTM_INT_PORT + ao_enable_port(AO_BTM_INT_PORT); + ao_exti_setup(AO_BTM_INT_PORT, AO_BTM_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_LOW, + ao_btm_isr); +#endif + +#if BT_CC1111 #if BT_LINK_ON_P1 /* * Configure ser reset line @@ -285,9 +487,7 @@ ao_btm_init (void) /* Enable interrupts */ IEN2 |= BT_IEN2_PIE; - - /* Check current pin state */ - ao_btm_check_link(); +#endif #if BT_LINK_ON_P2 /* Eable the pin interrupt */ @@ -299,4 +499,5 @@ ao_btm_init (void) #endif ao_add_task(&ao_btm_task, ao_btm, "bt"); + ao_btm_log_init(); }