diff options
| author | tmk <wakojun@gmail.com> | 2013-11-27 23:23:08 -0800 | 
|---|---|---|
| committer | tmk <wakojun@gmail.com> | 2013-11-27 23:23:08 -0800 | 
| commit | f3132adb33fd38e8d9d49845809ad5cb89f9c9c1 (patch) | |
| tree | 1ec0e2caca6ea8cf99c3e1d49e3a279f78523d99 /protocol | |
| parent | bc5b64d83259715667356770965a33aa620a8030 (diff) | |
| parent | f7db144959461d9b817752f7c6ca34b34d275cff (diff) | |
| download | firmware-f3132adb33fd38e8d9d49845809ad5cb89f9c9c1.tar.gz firmware-f3132adb33fd38e8d9d49845809ad5cb89f9c9c1.tar.bz2 firmware-f3132adb33fd38e8d9d49845809ad5cb89f9c9c1.zip | |
Merge pull request #81 from bgould/master
Add support for Adafruit's Bluefruit
Diffstat (limited to 'protocol')
| -rw-r--r-- | protocol/bluefruit.mk | 27 | ||||
| -rw-r--r-- | protocol/bluefruit/bluefruit.c | 202 | ||||
| -rw-r--r-- | protocol/bluefruit/bluefruit.h | 28 | ||||
| -rw-r--r-- | protocol/bluefruit/main.c | 116 | 
4 files changed, 373 insertions, 0 deletions
| diff --git a/protocol/bluefruit.mk b/protocol/bluefruit.mk new file mode 100644 index 000000000..7e6328f6c --- /dev/null +++ b/protocol/bluefruit.mk @@ -0,0 +1,27 @@ +BLUEFRUIT_DIR = protocol/bluefruit +PJRC_DIR = protocol/pjrc + +SRC +=	$(BLUEFRUIT_DIR)/main.c \ +	$(BLUEFRUIT_DIR)/bluefruit.c \ +	serial_uart.c \ +	$(PJRC_DIR)/pjrc.c \ +	$(PJRC_DIR)/usb_keyboard.c \ +	$(PJRC_DIR)/usb_debug.c \ +	$(PJRC_DIR)/usb.c + +# Option modules +ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) +    SRC += $(PJRC_DIR)/usb_mouse.c +endif + +ifdef EXTRAKEY_ENABLE +    SRC += $(PJRC_DIR)/usb_extra.c +endif + +# Search Path +VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR) +#VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR)/usb_debug_only +VPATH += $(TOP_DIR)/$(PJRC_DIR) + +OPT_DEFS += -DPROTOCOL_BLUEFRUIT +OPT_DEFS += -DPROTOCOL_PJRC diff --git a/protocol/bluefruit/bluefruit.c b/protocol/bluefruit/bluefruit.c new file mode 100644 index 000000000..f991e4d04 --- /dev/null +++ b/protocol/bluefruit/bluefruit.c @@ -0,0 +1,202 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +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, 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 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <stdint.h> +#include "host.h" +#include "report.h" +#include "print.h" +#include "debug.h" +#include "host_driver.h" +#include "serial.h" +#include "bluefruit.h" + +#define BLUEFRUIT_TRACE_SERIAL 1 + +static uint8_t bluefruit_keyboard_leds = 0; + +static void bluefruit_serial_send(uint8_t); + +void bluefruit_keyboard_print_report(report_keyboard_t *report) +{ +    if (!debug_keyboard) return; +    dprintf("keys: "); for (int i = 0; i < REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); } +    dprintf(" mods: "); debug_hex8(report->mods); +    dprintf(" reserved: "); debug_hex8(report->reserved);  +    dprintf("\n"); +} + +#ifdef BLUEFRUIT_TRACE_SERIAL +static void bluefruit_trace_header() +{ +    dprintf("+------------------------------------+\n"); +    dprintf("| HID report to Bluefruit via serial |\n"); +    dprintf("+------------------------------------+\n|"); +} + +static void bluefruit_trace_footer() +{ +    dprintf("|\n+------------------------------------+\n\n"); +} +#endif + +static void bluefruit_serial_send(uint8_t data) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL +    dprintf(" "); +    debug_hex8(data); +    dprintf(" "); +#endif +    serial_send(data); +} + +/*------------------------------------------------------------------* + * 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); + +static host_driver_t driver = { +        keyboard_leds, +        send_keyboard, +        send_mouse, +        send_system, +        send_consumer +}; + +host_driver_t *bluefruit_driver(void) +{ +    return &driver; +} + +static uint8_t keyboard_leds(void) { +    return bluefruit_keyboard_leds; +} + +static void send_keyboard(report_keyboard_t *report) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL    +    bluefruit_trace_header(); +#endif +    bluefruit_serial_send(0xFD); +    for (uint8_t i = 0; i < REPORT_SIZE; i++) { +        bluefruit_serial_send(report->raw[i]); +    } +#ifdef BLUEFRUIT_TRACE_SERIAL    +    bluefruit_trace_footer();    +#endif +} + +static void send_mouse(report_mouse_t *report) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL    +    bluefruit_trace_header(); +#endif +    bluefruit_serial_send(0xFD); +    bluefruit_serial_send(0x00); +    bluefruit_serial_send(0x03); +    bluefruit_serial_send(report->buttons); +    bluefruit_serial_send(report->x); +    bluefruit_serial_send(report->y); +    bluefruit_serial_send(report->v); // should try sending the wheel v here +    bluefruit_serial_send(report->h); // should try sending the wheel h here +    bluefruit_serial_send(0x00); +#ifdef BLUEFRUIT_TRACE_SERIAL +    bluefruit_trace_footer(); +#endif +} + +static void send_system(uint16_t data) +{ +} + +/* ++-----------------+-------------------+-------+ +| Consumer Key    | Bit Map           | Hex   | ++-----------------+-------------------+-------+ +| Home            | 00000001 00000000 | 01 00 | +| KeyboardLayout  | 00000010 00000000 | 02 00 | +| Search          | 00000100 00000000 | 04 00 | +| Snapshot        | 00001000 00000000 | 08 00 | +| VolumeUp        | 00010000 00000000 | 10 00 | +| VolumeDown      | 00100000 00000000 | 20 00 | +| Play/Pause      | 01000000 00000000 | 40 00 | +| Fast Forward    | 10000000 00000000 | 80 00 | +| Rewind          | 00000000 00000001 | 00 01 | +| Scan Next Track | 00000000 00000010 | 00 02 | +| Scan Prev Track | 00000000 00000100 | 00 04 | +| Random Play     | 00000000 00001000 | 00 08 | +| Stop            | 00000000 00010000 | 00 10 | ++-------------------------------------+-------+ +*/ +#define CONSUMER2BLUEFRUIT(usage) \ +    (usage == AUDIO_MUTE           ? 0x0000  : \ +    (usage == AUDIO_VOL_UP         ? 0x1000  : \ +    (usage == AUDIO_VOL_DOWN       ? 0x2000  : \ +    (usage == TRANSPORT_NEXT_TRACK ? 0x0002  : \ +    (usage == TRANSPORT_PREV_TRACK ? 0x0004  : \ +    (usage == TRANSPORT_STOP       ? 0x0010  : \ +    (usage == TRANSPORT_STOP_EJECT ? 0x0000  : \ +    (usage == TRANSPORT_PLAY_PAUSE ? 0x4000  : \ +    (usage == AL_CC_CONFIG         ? 0x0000  : \ +    (usage == AL_EMAIL             ? 0x0000  : \ +    (usage == AL_CALCULATOR        ? 0x0000  : \ +    (usage == AL_LOCAL_BROWSER     ? 0x0000  : \ +    (usage == AC_SEARCH            ? 0x0400  : \ +    (usage == AC_HOME              ? 0x0100  : \ +    (usage == AC_BACK              ? 0x0000  : \ +    (usage == AC_FORWARD           ? 0x0000  : \ +    (usage == AC_STOP              ? 0x0000  : \ +    (usage == AC_REFRESH           ? 0x0000  : \ +    (usage == AC_BOOKMARKS         ? 0x0000  : 0))))))))))))))))))) + +static void send_consumer(uint16_t data) +{ +    static uint16_t last_data = 0; +    if (data == last_data) return; +    last_data = data; +     +    uint16_t bitmap = CONSUMER2BLUEFRUIT(data); +     +#ifdef BLUEFRUIT_TRACE_SERIAL    +    dprintf("\nData: ");  +    debug_hex16(data);  +    dprintf("; bitmap: ");  +    debug_hex16(bitmap);  +    dprintf("\n"); +    bluefruit_trace_header(); +#endif +    bluefruit_serial_send(0xFD); +    bluefruit_serial_send(0x00); +    bluefruit_serial_send(0x02); +    bluefruit_serial_send((bitmap>>8)&0xFF); +    bluefruit_serial_send(bitmap&0xFF);  +    bluefruit_serial_send(0x00); +    bluefruit_serial_send(0x00); +    bluefruit_serial_send(0x00); +    bluefruit_serial_send(0x00); +#ifdef BLUEFRUIT_TRACE_SERIAL +    bluefruit_trace_footer(); +#endif +} + diff --git a/protocol/bluefruit/bluefruit.h b/protocol/bluefruit/bluefruit.h new file mode 100644 index 000000000..4f9b58836 --- /dev/null +++ b/protocol/bluefruit/bluefruit.h @@ -0,0 +1,28 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +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, 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 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef VUSB_H +#define VUSB_H + +#include "host_driver.h" + + +host_driver_t *bluefruit_driver(void); + +#endif diff --git a/protocol/bluefruit/main.c b/protocol/bluefruit/main.c new file mode 100644 index 000000000..871062ab1 --- /dev/null +++ b/protocol/bluefruit/main.c @@ -0,0 +1,116 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +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, 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 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <avr/sleep.h> +#include <util/delay.h> +#include "serial.h" +#include "keyboard.h" +#include "usb.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "debug.h" +#include "sendchar.h" +#include "suspend.h" +#include "bluefruit.h" +#include "pjrc.h" + +#define CPU_PRESCALE(n)    (CLKPR = 0x80, CLKPR = (n)) + +#define HOST_DRIVER_NOT_SET     0 +#define BLUEFRUIT_HOST_DRIVER   1 +#define PJRC_HOST_DRIVER        2 + +int main(void) +{    + +    CPU_PRESCALE(0); + +    DDRD  = _BV(PD5); +    DDRB  = _BV(PB0); +     +    PORTD = _BV(PD5); +    PORTB = _BV(PB0); + +    print_set_sendchar(sendchar); + +    usb_init(); +    _delay_ms(2000); +    // while (!usb_configured()) /* wait */ + +    dprintf("Initializing keyboard...\n"); +    keyboard_init(); +     +    // This implementation is pretty simplistic... if the USB connection +    // is not configured, choose the Bluefruit, otherwise use USB +    // Definitely would prefer to have this driven by an input pin and make +    // it switch dynamically - BCG +    if (!usb_configured()) { +     +        // Send power to Bluefruit... Adafruit says it takes 27 mA, I think +        // the pins should provide 40 mA, but just in case I switch the  +        // Bluefruit using a transistor - BCG +        DDRB   = _BV(PB6); +        PORTB |= _BV(PB6); +     +        dprintf("Setting host driver to bluefruit...\n"); +        host_set_driver(bluefruit_driver()); + +        dprintf("Initializing serial...\n"); +        serial_init(); +         +        // wait an extra second for the PC's operating system +        // to load drivers and do whatever it does to actually +        // be ready for input +        _delay_ms(1000); +        PORTD = ~_BV(PD5); +        dprintf("Starting main loop"); +        while (1) { +            keyboard_task(); +        } + +    } else { + +        // I'm not smart enough to get this done with LUFA - BCG +        dprintf("Setting host driver to PJRC...\n"); +        host_set_driver(pjrc_driver()); +#ifdef SLEEP_LED_ENABLE +    sleep_led_init(); +#endif +        // wait an extra second for the PC's operating system +        // to load drivers and do whatever it does to actually +        // be ready for input +        _delay_ms(1000); +        PORTB = ~_BV(PB0); +        dprintf("Starting main loop"); +        while (1) { +            while (suspend) { +                suspend_power_down(); +                if (remote_wakeup && suspend_wakeup_condition()) { +                    usb_remote_wakeup(); +                } +            } +            keyboard_task();  +        } +    } + +} | 
