2014-07-17 07:59:22 +00:00
# include <avr/io.h>
2014-06-25 04:57:36 +00:00
# include "host.h"
# include "host_driver.h"
2014-06-30 19:29:45 +00:00
# include "serial.h"
2014-06-25 04:57:36 +00:00
# include "rn42.h"
2014-06-30 19:29:45 +00:00
# include "print.h"
2015-01-10 17:39:32 +00:00
# include "timer.h"
2014-06-30 19:29:45 +00:00
# include "wait.h"
2014-06-25 04:57:36 +00:00
/* Host driver */
static uint8_t keyboard_leds ( void ) ;
static void send_keyboard ( report_keyboard_t * report ) ;
static void send_mouse ( report_mouse_t * report ) ;
static void send_system ( uint16_t data ) ;
static void send_consumer ( uint16_t data ) ;
host_driver_t rn42_driver = {
keyboard_leds ,
send_keyboard ,
send_mouse ,
send_system ,
send_consumer
} ;
2014-06-30 19:29:45 +00:00
void rn42_init ( void )
{
// JTAG disable for PORT F. write JTD bit twice within four cycles.
MCUCR | = ( 1 < < JTD ) ;
MCUCR | = ( 1 < < JTD ) ;
2014-07-28 06:12:00 +00:00
// PF7: BT connection control(high: connect, low: disconnect)
2014-06-30 19:29:45 +00:00
rn42_autoconnect ( ) ;
2014-07-28 06:12:00 +00:00
// PF6: linked(input without pull-up)
DDRF & = ~ ( 1 < < 6 ) ;
2014-08-30 06:59:41 +00:00
PORTF | = ( 1 < < 6 ) ;
2014-07-28 06:12:00 +00:00
2014-07-17 04:06:48 +00:00
// PF1: RTS(low: allowed to send, high: not allowed)
DDRF & = ~ ( 1 < < 1 ) ;
PORTF & = ~ ( 1 < < 1 ) ;
// PD5: CTS(low: allow to send, high:not allow)
2014-06-30 19:29:45 +00:00
DDRD | = ( 1 < < 5 ) ;
PORTD & = ~ ( 1 < < 5 ) ;
serial_init ( ) ;
}
2015-01-10 17:39:32 +00:00
int16_t rn42_getc ( void )
{
return serial_recv2 ( ) ;
}
2015-01-11 19:32:53 +00:00
const char * rn42_gets ( uint16_t timeout )
2015-01-10 17:39:32 +00:00
{
2015-01-11 19:32:53 +00:00
static char s [ 24 ] ;
2015-01-10 17:39:32 +00:00
uint16_t t = timer_read ( ) ;
uint8_t i = 0 ;
int16_t c ;
2015-01-11 19:32:53 +00:00
while ( i < 23 & & timer_elapsed ( t ) < timeout ) {
if ( ( c = rn42_getc ( ) ) ! = - 1 ) {
2015-01-10 17:39:32 +00:00
if ( ( char ) c = = ' \r ' ) continue ;
if ( ( char ) c = = ' \n ' ) break ;
s [ i + + ] = c ;
}
}
s [ i ] = ' \0 ' ;
return s ;
}
2014-06-30 19:29:45 +00:00
void rn42_putc ( uint8_t c )
{
serial_send ( c ) ;
}
2015-01-10 17:39:32 +00:00
void rn42_puts ( char * s )
{
while ( * s )
serial_send ( * s + + ) ;
}
2014-07-17 04:06:48 +00:00
bool rn42_autoconnecting ( void )
{
// GPIO6 for control connection(high: auto connect, low: disconnect)
// Note that this needs config: SM,4(Auto-Connect DTR Mode)
return ( PORTF & ( 1 < < 7 ) ? true : false ) ;
}
2014-06-30 19:29:45 +00:00
void rn42_autoconnect ( void )
{
2014-07-17 04:06:48 +00:00
// hi to auto connect
DDRF | = ( 1 < < 7 ) ;
PORTF | = ( 1 < < 7 ) ;
2014-06-30 19:29:45 +00:00
}
void rn42_disconnect ( void )
{
2014-07-17 04:06:48 +00:00
// low to disconnect
2014-06-30 19:29:45 +00:00
DDRF | = ( 1 < < 7 ) ;
PORTF & = ~ ( 1 < < 7 ) ;
}
2014-07-17 04:06:48 +00:00
bool rn42_rts ( void )
{
// low when RN-42 is powered and ready to receive
return PINF & ( 1 < < 1 ) ;
}
void rn42_cts_hi ( void )
2014-06-30 19:29:45 +00:00
{
2014-07-17 04:06:48 +00:00
// not allow to send
PORTD | = ( 1 < < 5 ) ;
}
void rn42_cts_lo ( void )
{
// allow to send
PORTD & = ~ ( 1 < < 5 ) ;
2014-06-30 19:29:45 +00:00
}
2014-07-23 03:23:00 +00:00
bool rn42_linked ( void )
{
2014-08-30 06:59:41 +00:00
// RN-42 GPIO2
// Hi-Z: Not powered
// High: Linked
// Low: Connecting
2015-01-11 19:32:53 +00:00
return PINF & ( 1 < < 6 ) ;
2014-07-23 03:23:00 +00:00
}
2014-06-30 19:29:45 +00:00
2014-09-22 05:20:49 +00:00
static uint8_t leds = 0 ;
static uint8_t keyboard_leds ( void ) { return leds ; }
void rn42_set_leds ( uint8_t l ) { leds = l ; }
2014-06-25 04:57:36 +00:00
static void send_keyboard ( report_keyboard_t * report )
{
2014-06-30 19:29:45 +00:00
// wake from deep sleep
2014-07-14 06:20:10 +00:00
/*
2014-06-30 19:29:45 +00:00
PORTD | = ( 1 < < 5 ) ; // high
wait_ms ( 5 ) ;
PORTD & = ~ ( 1 < < 5 ) ; // low
2014-07-14 06:20:10 +00:00
*/
2014-06-30 19:29:45 +00:00
serial_send ( 0xFD ) ; // Raw report mode
serial_send ( 9 ) ; // length
serial_send ( 1 ) ; // descriptor type
serial_send ( report - > mods ) ;
serial_send ( 0x00 ) ;
serial_send ( report - > keys [ 0 ] ) ;
serial_send ( report - > keys [ 1 ] ) ;
serial_send ( report - > keys [ 2 ] ) ;
serial_send ( report - > keys [ 3 ] ) ;
serial_send ( report - > keys [ 4 ] ) ;
serial_send ( report - > keys [ 5 ] ) ;
2014-06-25 04:57:36 +00:00
}
static void send_mouse ( report_mouse_t * report )
{
2014-06-30 19:29:45 +00:00
// wake from deep sleep
2014-07-14 06:20:10 +00:00
/*
2014-06-30 19:29:45 +00:00
PORTD | = ( 1 < < 5 ) ; // high
wait_ms ( 5 ) ;
PORTD & = ~ ( 1 < < 5 ) ; // low
2014-07-14 06:20:10 +00:00
*/
2014-06-30 19:29:45 +00:00
serial_send ( 0xFD ) ; // Raw report mode
serial_send ( 5 ) ; // length
serial_send ( 2 ) ; // descriptor type
serial_send ( report - > buttons ) ;
serial_send ( report - > x ) ;
serial_send ( report - > y ) ;
serial_send ( report - > v ) ;
2014-06-25 04:57:36 +00:00
}
static void send_system ( uint16_t data )
{
2014-06-30 19:29:45 +00:00
// Table 5-6 of RN-BT-DATA-UB
// 81,82,83 scan codes can be used?
}
static uint16_t usage2bits ( uint16_t usage )
{
switch ( usage ) {
2016-03-28 22:00:56 +00:00
case APPCONTROL_HOME : return 0x01 ;
case APPLAUNCH_EMAIL : return 0x02 ;
case APPCONTROL_SEARCH : return 0x04 ;
2014-06-30 19:29:45 +00:00
//case AL_KBD_LAYOUT: return 0x08; // Apple virtual keybaord toggle
2015-11-07 16:00:28 +00:00
case AUDIO_VOL_UP : return 0x10 ;
case AUDIO_VOL_DOWN : return 0x20 ;
case AUDIO_MUTE : return 0x40 ;
case TRANSPORT_PLAY_PAUSE : return 0x80 ;
case TRANSPORT_NEXT_TRACK : return 0x100 ;
case TRANSPORT_PREV_TRACK : return 0x200 ;
case TRANSPORT_STOP : return 0x400 ;
case TRANSPORT_STOP_EJECT : return 0x800 ;
case TRANSPORT_FAST_FORWARD : return 0x1000 ;
case TRANSPORT_REWIND : return 0x2000 ;
2014-06-30 19:29:45 +00:00
//case return 0x4000; // Stop/eject
//case return 0x8000; // Internet browser
} ;
return 0 ;
2014-06-25 04:57:36 +00:00
}
static void send_consumer ( uint16_t data )
{
2014-06-30 19:29:45 +00:00
uint16_t bits = usage2bits ( data ) ;
serial_send ( 0xFD ) ; // Raw report mode
serial_send ( 3 ) ; // length
serial_send ( 3 ) ; // descriptor type
serial_send ( bits & 0xFF ) ;
2014-07-01 01:16:19 +00:00
serial_send ( ( bits > > 8 ) & 0xFF ) ;
2014-06-25 04:57:36 +00:00
}
2014-06-30 19:29:45 +00:00
/* Null driver for config_mode */
static uint8_t config_keyboard_leds ( void ) ;
static void config_send_keyboard ( report_keyboard_t * report ) ;
static void config_send_mouse ( report_mouse_t * report ) ;
static void config_send_system ( uint16_t data ) ;
static void config_send_consumer ( uint16_t data ) ;
host_driver_t rn42_config_driver = {
config_keyboard_leds ,
config_send_keyboard ,
config_send_mouse ,
config_send_system ,
config_send_consumer
} ;
2014-09-22 05:20:49 +00:00
static uint8_t config_keyboard_leds ( void ) { return leds ; }
2014-06-30 19:29:45 +00:00
static void config_send_keyboard ( report_keyboard_t * report ) { }
static void config_send_mouse ( report_mouse_t * report ) { }
static void config_send_system ( uint16_t data ) { }
static void config_send_consumer ( uint16_t data ) { }