*
* 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
*/
#include "ao.h"
+#ifdef AO_BTM_INT_PORT
+#include <ao_exti.h>
+#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
-#define ao_serial_btm_rx_fifo ao_serial1_rx_fifo
#endif
-int8_t ao_btm_stdio;
-__xdata uint8_t ao_btm_connected;
+uint8_t ao_btm_stdio;
+uint8_t ao_btm_connected;
#define BT_DEBUG 0
#if BT_DEBUG
-__xdata char ao_btm_buffer[256];
-int ao_btm_ptr;
+char ao_btm_buffer[256];
+uint16_t ao_btm_ptr;
char ao_btm_dir;
static void
{
int i;
char c;
+ uint16_t r;
for (i = 0; i < ao_btm_ptr; i++) {
c = ao_btm_buffer[i];
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)
{
- ao_cmd_decimal();
- if (ao_cmd_lex_u32 == 57600)
+ switch (ao_cmd_decimal()) {
+ case 57600:
ao_serial_btm_set_speed(AO_SERIAL_SPEED_57600);
- else if (ao_cmd_lex_u32 == 19200)
+ break;
+ case 19200:
ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200);
- else
+ 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();
}
-__code struct ao_cmds ao_btm_cmds[] = {
+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 },
};
#endif
#define AO_BTM_MAX_REPLY 16
-__xdata char ao_btm_reply[AO_BTM_MAX_REPLY];
+char ao_btm_reply[AO_BTM_MAX_REPLY];
/*
* Read one bluetooth character.
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
- ao_alarm(AO_MS_TO_TICKS(10));
- c = ao_sleep(&ao_serial_btm_rx_fifo);
- ao_clear_alarm();
+ c = _ao_serial_btm_sleep_for(AO_MS_TO_TICKS(10));
if (c) {
c = AO_READ_AGAIN;
break;
* it after a few characters.
*/
-uint8_t
+static uint8_t
ao_btm_get_line(void)
{
uint8_t ao_btm_reply_len = 0;
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;
+ ao_btm_reply[ao_btm_reply_len++] = (char) c;
if (c == '\r' || c == '\n')
break;
}
- 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;
}
/*
* Drain the serial port completely
*/
-void
-ao_btm_drain()
+static void
+ao_btm_drain(void)
{
while (ao_btm_get_line())
;
/*
* Set the stdio echo for the bluetooth link
*/
-void
+static void
ao_btm_echo(uint8_t echo)
{
ao_stdios[ao_btm_stdio].echo = echo;
* can't keep up with 57600 baud
*/
-void
+static void
ao_btm_putchar(char c)
{
ao_btm_log_out_char(c);
* Wait for the bluetooth device to return
* status from the previously executed command
*/
-uint8_t
+static int
ao_btm_wait_reply(void)
{
for (;;) {
}
}
-void
-ao_btm_string(__code char *cmd)
+static void
+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)
+static int
+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();
}
-uint8_t
+static int
ao_btm_set_name(void)
{
char sn[8];
*--s = '\r';
n = ao_serial_number;
do {
- *--s = '0' + n % 10;
+ *--s = (uint8_t) ('0' + n % 10);
} while (n /= 10);
while ((c = *s++))
ao_btm_putchar(c);
return ao_btm_wait_reply();
}
-uint8_t
+static uint8_t
ao_btm_try_speed(uint8_t speed)
{
ao_serial_btm_set_speed(speed);
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
+
+static void
+ao_btm_check_link(void)
+{
+#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
*/
-void
+static 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
*/
/* Turn off status reporting */
ao_btm_cmd("ATQ1\r");
+ 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()
-{
- 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;
- }
- );
-}
+#if BT_CC1111
void
ao_btm_isr(void)
#if BT_LINK_ON_P1
}
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_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
/* Enable interrupts */
IEN2 |= BT_IEN2_PIE;
-
- /* Check current pin state */
- ao_btm_check_link();
+#endif
#if BT_LINK_ON_P2
/* Eable the pin interrupt */