diff options
| author | Keith Packard <keithp@keithp.com> | 2011-04-07 22:00:38 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2011-04-07 22:00:38 -0700 | 
| commit | 1a54a58d72147888f783a3caf364479efff4ed9b (patch) | |
| tree | 20d3352c5cc17ac5c55ca52df63a21e95d5d73ed | |
| parent | f28efe271f9670473249574f6bcf6e160fe58c7b (diff) | |
altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init.
PIo(6) appears to be an active-low indication of the Bluetooth
connection status. Hook this up using an interrupt to track the
link state instead of using in-band status messages.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | src/ao.h | 5 | ||||
| -rw-r--r-- | src/ao_btm.c | 229 | ||||
| -rw-r--r-- | src/ao_pins.h | 1 | ||||
| -rw-r--r-- | src/ao_usb.c | 4 | ||||
| -rw-r--r-- | src/cc1111.h | 8 | 
5 files changed, 203 insertions, 44 deletions
@@ -107,6 +107,7 @@ ao_start_scheduler(void);  #define AO_PANIC_REBOOT		8	/* Reboot failed */  #define AO_PANIC_FLASH		9	/* Invalid flash part (or wrong blocksize) */  #define AO_PANIC_USB		10	/* Trying to send USB packet while busy */ +#define AO_PANIC_BT		11	/* Communications with bluetooth device failed */  /* Stop the operating system, beeping and blinking the reason */  void @@ -1366,6 +1367,10 @@ ao_packet_slave_init(uint8_t enable);  /* ao_btm.c */ +/* Shared by USB, so the USB code calls this function */ +void +ao_btm_isr(void); +  void  ao_btm_init(void); diff --git a/src/ao_btm.c b/src/ao_btm.c index c7024ed3..71907f86 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -18,12 +18,47 @@  #include "ao.h"  uint8_t			ao_btm_running; -uint8_t			ao_btm_stdio; +int8_t			ao_btm_stdio;  __xdata uint8_t		ao_btm_connected;  uint8_t			ao_btm_chat;  __xdata char		ao_btm_buffer[1024];  int			ao_btm_ptr; +char			ao_btm_dir; + +uint8_t			ao_btm_send_chars = 0; + +void +ao_btm_putchar(char c); + +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, '<'); +}  #define AO_BTM_MAX_REPLY	16  __xdata char		ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -44,10 +79,9 @@ ao_btm_get_line(void)  	for (;;) {  		while ((c = ao_serial_pollchar()) != 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 (ao_btm_ptr < sizeof (ao_btm_buffer)) -				ao_btm_buffer[ao_btm_ptr++] = c;  			if (c == '\r' || c == '\n')  				goto done;  		} @@ -89,20 +123,14 @@ ao_btm_echo(uint8_t echo)  uint8_t  ao_cmd_filter(void)  { +	if (ao_cur_stdio != ao_btm_stdio) +		return 0;  	ao_cmd_lex();  	while (ao_cmd_lex_c != '\n') { -		if (ao_match_word("CONNECT")) { -			ao_btm_connected = 1; -			ao_btm_echo(1); -			ao_wakeup(&ao_btm_connected); +		if (ao_match_word("CONNECT"))  			return 1; -		} -		if (ao_match_word("DISCONNECT")) { -			ao_btm_connected = 0; -			ao_btm_echo(0); -			ao_wakeup(&ao_btm_connected); +		if (ao_match_word("DISCONNECT"))  			return 1; -		}  		if (ao_match_word("ERROR"))  			return 1;  		if (ao_match_word("OK")) @@ -126,11 +154,25 @@ ao_btm_pollchar(void)  		return AO_READ_AGAIN;  	c = ao_serial_pollchar();  	if (c != AO_READ_AGAIN) -		if (ao_btm_ptr < sizeof (ao_btm_buffer)) -			ao_btm_buffer[ao_btm_ptr++] = c; +		ao_btm_log_in_char(c);  	return c;  } +void +ao_btm_putchar(char c) +{ +	if (!ao_btm_send_chars) { +		ao_btm_log_out_char(c); +		ao_serial_putchar(c); +	} +} + +void +ao_btm_stdio_putchar(char c) { +	if (ao_btm_connected) +		ao_btm_putchar(c); +} +  /*   * Wait for the bluetooth device to return   * status from the previously executed command @@ -140,9 +182,9 @@ ao_btm_wait_reply(void)  {  	for (;;) {  		ao_btm_get_line(); -		if (!strcmp(ao_btm_reply, "OK")) +		if (!strncmp(ao_btm_reply, "OK", 2))  			return 1; -		if (!strcmp(ao_btm_reply, "ERROR")) +		if (!strncmp(ao_btm_reply, "ERROR", 5))  			return -1;  		if (ao_btm_reply[0] == '\0')  			return 0; @@ -150,13 +192,50 @@ ao_btm_wait_reply(void)  }  void +ao_btm_string(__code char *cmd) +{ +	char	c; + +	while (c = *cmd++) +		ao_btm_putchar(c); +} + +uint8_t  ao_btm_cmd(__code char *cmd)  { -	ao_cur_stdio = ao_btm_stdio; -	printf(cmd); -	ao_btm_wait_reply(); +	ao_btm_drain(); +	ao_btm_string(cmd); +	return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_set_name(void) +{ +	char	sn[7]; +	char	*s = sn + 7; +	char	c; +	int	n; +	ao_btm_string("ATN=TeleBT-"); +	*--s = '\0'; +	n = ao_serial_number; +	do { +		*--s = '0' + n % 10; +	} while (n /= 10); +	while ((c = *s++)) +		ao_btm_putchar(c); +	return ao_btm_wait_reply();  } +uint8_t +ao_btm_try_speed(uint8_t speed) +{ +	ao_serial_set_speed(speed); +	ao_btm_drain(); +	(void) ao_btm_cmd("\rATE0\rATQ0\r"); +	if (ao_btm_cmd("AT\r") == 1) +		return 1; +	return 0; +}  /*   * A thread to initialize the bluetooth device and   * hang around to blink the LED when connected @@ -164,30 +243,36 @@ ao_btm_cmd(__code char *cmd)  void  ao_btm(void)  { -	ao_serial_set_speed(AO_SERIAL_SPEED_19200);  	ao_add_stdio(ao_btm_pollchar, -		     ao_serial_putchar, +		     ao_btm_stdio_putchar,  		     NULL);  	ao_btm_stdio = ao_num_stdios - 1; -	ao_cur_stdio = ao_btm_stdio;  	ao_btm_echo(0); -	ao_btm_drain(); -	ao_delay(AO_SEC_TO_TICKS(1)); -	printf("+++"); -	ao_btm_drain(); -	ao_delay(AO_SEC_TO_TICKS(1)); -	printf("\r"); -	ao_btm_drain(); -	ao_btm_cmd("ATQ0\r"); + +	/* +	 * 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 +	 * if it is already running at 57600 baud, and if that doesn't work +	 * then tell it to switch to 57600 from 19200 baud. +	 */ +	while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { +		if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) +			ao_btm_cmd("ATL4\r"); +		ao_delay(AO_SEC_TO_TICKS(1)); +	} + +	/* Disable echo */  	ao_btm_cmd("ATE0\r"); -	ao_btm_cmd("ATH\r"); -	ao_delay(AO_SEC_TO_TICKS(1)); -	ao_btm_cmd("ATC0\r"); -	ao_btm_cmd("ATL4\r"); -	ao_serial_set_speed(AO_SERIAL_SPEED_57600); -	ao_btm_drain(); -	printf("ATN=TeleBT-%d\r", ao_serial_number); -	ao_btm_wait_reply(); + +	/* Enable flow control */ +	ao_btm_cmd("ATC1\r"); + +	/* Set the reported name to something we can find on the host */ +	ao_btm_set_name(); + +	/* Turn off status reporting */ +	ao_btm_cmd("ATQ1\r"); +  	ao_btm_running = 1;  	for (;;) {  		while (!ao_btm_connected && !ao_btm_chat) @@ -197,9 +282,10 @@ ao_btm(void)  			while (ao_btm_chat) {  				char	c;  				c = ao_serial_pollchar(); -				if (c != AO_READ_AGAIN) +				if (c != AO_READ_AGAIN) { +					ao_btm_log_in_char(c);  					ao_usb_putchar(c); -				else { +				} else {  					ao_usb_flush();  					ao_sleep(&ao_usart1_rx_fifo);  				} @@ -229,7 +315,7 @@ ao_btm_forward(void)  	ao_usb_flush();  	while ((c = ao_usb_getchar()) != '~') {  		if (c == '\n') c = '\r'; -		ao_serial_putchar(c); +		ao_btm_putchar(c);  	}  	ao_btm_chat = 0;  	while (!ao_btm_running) { @@ -245,15 +331,56 @@ static void  ao_btm_dump(void)  {  	int i; +	char c; -	for (i = 0; i < ao_btm_ptr; i++) -		putchar(ao_btm_buffer[i]); +	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');  } +static void +ao_btm_speed(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_lex_u32 == 57600) +		ao_serial_set_speed(AO_SERIAL_SPEED_57600); +	else if (ao_cmd_lex_u32 == 19200) +		ao_serial_set_speed(AO_SERIAL_SPEED_19200); +	else +		ao_cmd_status = ao_cmd_syntax_error; +} + +void +ao_btm_check_link() __critical +{ +	if (P2_1) { +		ao_btm_connected = 0; +		PICTL |= PICTL_P2ICON; +	} else { +		ao_btm_connected = 1; +		PICTL &= ~PICTL_P2ICON; +	} +} + +void +ao_btm_isr(void) +{ +	if (P2IFG & (1 << 1)) { +		ao_btm_check_link(); +		ao_wakeup(&ao_btm_connected); +	} +	P2IFG = 0; +} +  __code struct ao_cmds ao_btm_cmds[] = {  	{ ao_btm_forward,	"B\0BTM serial link." },  	{ ao_btm_dump,		"d\0Dump btm buffer." }, +	{ ao_btm_speed,		"s <19200,57600>\0Set btm serial speed." },  	{ 0, NULL },  }; @@ -262,6 +389,20 @@ ao_btm_init (void)  {  	ao_serial_init();  	ao_serial_set_speed(AO_SERIAL_SPEED_19200); + +	/* +	 * Configure link status line +	 */ + +	/* Set P2_1 to input, pull-down */ +	P2DIR &= ~(1 << 1); +	P2INP |= P2INP_MDP2_1_TRISTATE; + +	/* Enable P2 interrupts */ +	IEN2 |= IEN2_P2IE; +	ao_btm_check_link(); +	PICTL |= PICTL_P2IEN; +  	ao_add_task(&ao_btm_task, ao_btm, "bt");  	ao_cmd_register(&ao_btm_cmds[0]);  } diff --git a/src/ao_pins.h b/src/ao_pins.h index ed42df8b..1344dcaa 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -228,6 +228,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			1  	#define HAS_EEPROM		0 +	#define HAS_BTM			1  	#define DBG_ON_P1 		0  	#define DBG_ON_P0 		1  	#define IGNITE_ON_P2		0 diff --git a/src/ao_usb.c b/src/ao_usb.c index b4e3f1fe..ece6756a 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -46,6 +46,7 @@ void  ao_usb_isr(void) __interrupt 6  {  	USBIF = 0; +	IRCON2 &= ~IRCON2_USBIF;  	ao_usb_iif |= USBIIF;  	if (ao_usb_iif & 1)  		ao_wakeup(&ao_usb_task); @@ -57,6 +58,9 @@ ao_usb_isr(void) __interrupt 6  	if (USBCIF & USBCIF_RSTIF)  		ao_usb_set_interrupts(); +#if HAS_BTM +	ao_btm_isr(); +#endif  }  struct ao_usb_setup { diff --git a/src/cc1111.h b/src/cc1111.h index a72d7416..a07490e5 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -662,6 +662,14 @@ sfr at 0x8B P2IFG;  #define P0IFG_USB_RESUME	(1 << 7) +sfr at 0x8C PICTL; +#define PICTL_P2IEN	(1 << 5) +#define PICTL_P0IENH	(1 << 4) +#define PICTL_P0IENL	(1 << 3) +#define PICTL_P2ICON	(1 << 2) +#define PICTL_P1ICON	(1 << 1) +#define PICTL_P0ICON	(1 << 0) +  /* GPIO pins */  sfr at 0x80 P0;  | 
