bluetooth

This commit is contained in:
Jack Humbert 2015-10-22 13:37:45 -04:00
parent 40148c430e
commit c966e7982c
20 changed files with 2329 additions and 319 deletions

View File

@ -68,6 +68,10 @@ ifdef BACKLIGHT_ENABLE
OPT_DEFS += -DBACKLIGHT_ENABLE OPT_DEFS += -DBACKLIGHT_ENABLE
endif endif
ifdef BLUETOOTH_ENABLE
OPT_DEFS += -DBLUETOOTH_ENABLE
endif
ifdef KEYMAP_SECTION_ENABLE ifdef KEYMAP_SECTION_ENABLE
OPT_DEFS += -DKEYMAP_SECTION_ENABLE OPT_DEFS += -DKEYMAP_SECTION_ENABLE
EXTRALDFLAGS = -Wl,-L$(TOP_DIR),-Tldscript_keymap_avr5.x EXTRALDFLAGS = -Wl,-L$(TOP_DIR),-Tldscript_keymap_avr5.x

View File

@ -39,7 +39,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// ┌─ 2u ────────────┐ // ┌─ 2u ────────────┐
// │ X │ // │ X │
// └─────────────────┘ // └─────────────────┘
{ KC_LCTL, KC_LGUI, KC_LALT, KC_LGUI, KC_LCTL, KC_SPC, KC_SPC, KC_RALT, KC_RGUI, KC_RALT, KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT }, { BL_STEP, KC_LCTL, KC_LALT, KC_LGUI, KC_LGUI, KC_SPC, KC_SPC, KC_RGUI, KC_RGUI, KC_RALT, KC_RCTL, BL_STEP, KC_LEFT, KC_DOWN, KC_RGHT },
// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐ // ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ // │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘ // └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

View File

@ -1,3 +1,3 @@
dfu-programmer atmega32u4 erase --force dfu-programmer atmega32u4 erase --force
dfu-programmer atmega32u4 flash planck_pcb.hex dfu-programmer atmega32u4 flash atomic_pcb.hex
dfu-programmer atmega32u4 reset dfu-programmer atmega32u4 reset

View File

@ -121,15 +121,16 @@ EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400) CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration COMMAND_ENABLE = yes # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend # SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
# NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA # NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
MIDI_ENABLE = YES # MIDI controls # MIDI_ENABLE = YES # MIDI controls
# UNICODE_ENABLE = YES # Unicode # UNICODE_ENABLE = YES # Unicode
# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
ifdef MIDI_ENABLE ifdef MIDI_ENABLE
SRC += keymap_midi.c \ SRC += keymap_midi.c
beeps.c # beeps.c
endif endif
ifdef UNICODE_ENABLE ifdef UNICODE_ENABLE
@ -143,7 +144,18 @@ endif
VPATH += $(TARGET_DIR) VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR) VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
ifdef BLUETOOTH_ENABLE
BLUEFRUIT_TRACE_SERIAL=true
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/protocol/bluefruit.mk
include $(TOP_DIR)/protocol.mk
else
include $(TOP_DIR)/protocol/lufa.mk
endif
include $(TOP_DIR)/common.mk include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk include $(TOP_DIR)/rules.mk

View File

@ -58,16 +58,83 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
) )
#ifdef BLUETOOTH_ENABLE
#ifdef __AVR_ATmega32U4__
#define SERIAL_UART_BAUD 9600
#define SERIAL_UART_DATA UDR1
#define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
#define SERIAL_UART_RXD_VECT USART1_RX_vect
#define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1))
#define SERIAL_UART_INIT() do { \
UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \
UCSR1B = (1<<TXEN1); /* TX: enable */ \
UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \
(0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \
sei(); \
} while(0)
#else
# error "USART configuration is needed."
#endif
// I'm fairly sure these aren't needed, but oh well - Jack
/*
* PS/2 Interrupt configuration
*/
#ifdef PS2_USE_INT
/* uses INT1 for clock line(ATMega32U4) */
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \
(0<<ISC10)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT1); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT1); \
} while (0)
#define PS2_INT_VECT INT1_vect
#endif
/*
* PS/2 Busywait configuration
*/
#ifdef PS2_USE_BUSYWAIT
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
#endif
#endif
/* /*
* Feature disable options * Feature disable options
* These options are also useful to firmware size reduction. * These options are also useful to firmware size reduction.
*/ */
/* disable debug print */ /* disable debug print */
#define NO_DEBUG // #define NO_DEBUG
/* disable print */ /* disable print */
#define NO_PRINT // #define NO_PRINT
/* disable action features */ /* disable action features */
//#define NO_ACTION_LAYER //#define NO_ACTION_LAYER

View File

@ -35,7 +35,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) { if (record->event.pressed) {
starting_note++; starting_note++;
// play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC); play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0); midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0); midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0); midi_send_cc(&midi_device, 2, 0x7B, 0);
@ -43,15 +43,15 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
midi_send_cc(&midi_device, 4, 0x7B, 0); midi_send_cc(&midi_device, 4, 0x7B, 0);
return; return;
} else { } else {
// stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1))); stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
// stop_all_notes(); stop_all_notes();
return; return;
} }
} }
if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) { if (record->event.pressed) {
starting_note--; starting_note--;
// play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC); play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0); midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0); midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0); midi_send_cc(&midi_device, 2, 0x7B, 0);
@ -59,8 +59,8 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
midi_send_cc(&midi_device, 4, 0x7B, 0); midi_send_cc(&midi_device, 4, 0x7B, 0);
return; return;
} else { } else {
// stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1))); stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
// stop_all_notes(); stop_all_notes();
return; return;
} }
} }
@ -72,13 +72,13 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
midi_send_cc(&midi_device, 2, 0x7B, 0); midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0); midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0); midi_send_cc(&midi_device, 4, 0x7B, 0);
// stop_all_notes(); stop_all_notes();
// for (int i = 0; i <= 7; i++) { for (int i = 0; i <= 7; i++) {
// play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC); play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
// _delay_us(80000); _delay_us(80000);
// stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1))); stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
// _delay_us(8000); _delay_us(8000);
// } }
return; return;
} }
if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
@ -88,23 +88,23 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
midi_send_cc(&midi_device, 2, 0x7B, 0); midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0); midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0); midi_send_cc(&midi_device, 4, 0x7B, 0);
// stop_all_notes(); stop_all_notes();
// for (int i = 0; i <= 7; i++) { for (int i = 0; i <= 7; i++) {
// play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC); play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
// _delay_us(80000); _delay_us(80000);
// stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1))); stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
// _delay_us(8000); _delay_us(8000);
// } }
return; return;
} }
if (record->event.pressed) { if (record->event.pressed) {
// midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); // midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127); midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
// play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF); play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
} else { } else {
// midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127); midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
// stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row))); stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
} }
} }

View File

@ -2,7 +2,7 @@
#include "backlight.h" #include "backlight.h"
#include "action_layer.h" #include "action_layer.h"
#include "keymap_midi.h" #include "keymap_midi.h"
#include "beeps.h" #include <avr/boot.h>
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = { /* Qwerty */ [0] = { /* Qwerty */
@ -53,6 +53,16 @@ const uint16_t PROGMEM fn_actions[] = {
}; };
uint16_t hextokeycode(int hex) {
if (hex == 0x0) {
return KC_0;
} else if (hex < 0xA) {
return KC_1 + (hex - 0x1);
} else {
return KC_A + (hex - 0xA);
}
}
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{ {
// MACRODOWN only works in this function // MACRODOWN only works in this function
@ -64,6 +74,35 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
backlight_set(BACKLIGHT_LEVELS); backlight_set(BACKLIGHT_LEVELS);
default_layer_and(0); default_layer_and(0);
default_layer_or((1<<5)); default_layer_or((1<<5));
uint8_t low = boot_lock_fuse_bits_get(0x0000);
uint8_t high = boot_lock_fuse_bits_get(0x0003);
uint8_t ext = boot_lock_fuse_bits_get(0x0002);
uint8_t lock = boot_lock_fuse_bits_get(0x0001);
register_code(hextokeycode((low & 0xF0) >> 4));
unregister_code(hextokeycode((low & 0xF0) >> 4));
register_code(hextokeycode((low & 0x0F)));
unregister_code(hextokeycode((low & 0x0F)));
register_code(hextokeycode((high & 0xF0) >> 4));
unregister_code(hextokeycode((high & 0xF0) >> 4));
register_code(hextokeycode((high & 0x0F)));
unregister_code(hextokeycode((high & 0x0F)));
register_code(hextokeycode((ext & 0xF0) >> 4));
unregister_code(hextokeycode((ext & 0xF0) >> 4));
register_code(hextokeycode((ext & 0x0F)));
unregister_code(hextokeycode((ext & 0x0F)));
register_code(hextokeycode((lock & 0xF0) >> 4));
unregister_code(hextokeycode((lock & 0xF0) >> 4));
register_code(hextokeycode((lock & 0x0F)));
unregister_code(hextokeycode((lock & 0x0F)));
// note(0+12, 20); // note(0+12, 20);
// note(0+24, 20); // note(0+24, 20);
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -127,7 +127,8 @@ MIDI_ENABLE = yes # MIDI controls
BACKLIGHT_ENABLE = yes BACKLIGHT_ENABLE = yes
ifdef MIDI_ENABLE ifdef MIDI_ENABLE
SRC += keymap_midi.c SRC += keymap_midi.c \
beeps.c
endif endif
# Optimize size but this may cause error "relocation truncated to fit" # Optimize size but this may cause error "relocation truncated to fit"

View File

@ -5,31 +5,6 @@
#include <avr/io.h> #include <avr/io.h>
#define PI 3.14159265 #define PI 3.14159265
#define CHANNEL OCR1C
volatile uint16_t sample;
uint16_t lastSample;
const int sounddata_length=200;
const unsigned char sounddata_data[] PROGMEM = {128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 129, 127, 129, 128, 127, 133,
117, 109, 125, 121, 116, 132, 140, 126, 114, 114, 116, 120, 114, 93, 73, 66, 76, 116, 142, 129,
128, 129, 120, 119, 118, 104, 87, 123, 181, 194, 196, 198, 189, 176, 160, 162, 172, 164, 164, 183,
197, 188, 168, 167, 170, 165, 185, 209, 206, 196, 196, 199, 185, 162, 156, 167, 176, 173, 170, 166,
151, 142, 140, 134, 130, 127, 113, 86, 67, 66, 69, 75, 73, 75, 86, 90, 91, 84, 65, 48,
41, 30, 26, 56, 91, 88, 72, 70, 73, 82, 89, 73, 57, 60, 74, 89, 92, 77, 63, 60,
53, 47, 56, 64, 63, 61, 56, 54, 52, 36, 16, 22, 51, 66, 67, 70, 76, 88, 99, 92,
77, 74, 85, 100, 106, 97, 83, 85, 96, 108, 133, 160, 164};
void delay_us(int count) { void delay_us(int count) {
while(count--) { while(count--) {
@ -37,202 +12,235 @@ void delay_us(int count) {
} }
} }
int voices = 0;
double frequency = 0;
int volume = 0;
int position = 0;
double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
bool sliding = false;
#define RANGE 1000
volatile int i=0; //elements of the wave
void beeps() { void beeps() {
// DDRB |= (1<<7); play_notes();
// PORTB &= ~(1<<7);
// // Use full 16-bit resolution.
// ICR1 = 0xFFFF;
// // I could write a wall of text here to explain... but TL;DW
// // Go read the ATmega32u4 datasheet.
// // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
// // Pin PB7 = OCR1C (Timer 1, Channel C)
// // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
// // (i.e. start high, go low when counter matches.)
// // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
// // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
// TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
// TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
// // Turn off PWM control on PB7, revert to output low.
// // TCCR1A &= ~(_BV(COM1C1));
// // CHANNEL = ((1 << level) - 1);
// // Turn on PWM control of PB7
// TCCR1A |= _BV(COM1C1);
// // CHANNEL = level << OFFSET | 0x0FFF;
// // CHANNEL = 0b1010101010101010;
// float x = 12;
// float y = 24;
// float length = 50;
// float scale = 1;
// // int f1 = 1000000/440;
// // int f2 = 1000000/880;
// // for (uint32_t i = 0; i < length * 1000; i++) {
// // // int frequency = 1/((sin(PI*2*i*scale*pow(2, x/12.0))*.5+1 + sin(PI*2*i*scale*pow(2, y/12.0))*.5+1) / 2);
// // ICR1 = f1; // Set max to the period
// // OCR1C = f1 >> 1; // Set compare to half the period
// // // _delay_us(10);
// // }
// int frequency = 1000000/440;
// ICR1 = frequency; // Set max to the period
// OCR1C = frequency >> 1; // Set compare to half the period
// _delay_us(500000);
// TCCR1A &= ~(_BV(COM1C1));
// CHANNEL = 0;
play_notes();
// play_note(55*pow(2, 0/12.0), 1);
// play_note(55*pow(2, 12/12.0), 1);
// play_note(55*pow(2, 24/12.0), 1);
// play_note(55*pow(2, 0/12.0), 1);
// play_note(55*pow(2, 12/12.0), 1);
// play_note(55*pow(2, 24/12.0), 1);
// play_note(0, 4);
// play_note(55*pow(2, 0/12.0), 8);
// play_note(55*pow(2, 12/12.0), 4);
// play_note(55*pow(2, 10/12.0), 4);
// play_note(55*pow(2, 12/12.0), 8);
// play_note(55*pow(2, 10/12.0), 4);
// play_note(55*pow(2, 7/12.0), 2);
// play_note(55*pow(2, 8/12.0), 2);
// play_note(55*pow(2, 7/12.0), 16);
// play_note(0, 4);
// play_note(55*pow(2, 3/12.0), 8);
// play_note(55*pow(2, 5/12.0), 4);
// play_note(55*pow(2, 7/12.0), 4);
// play_note(55*pow(2, 7/12.0), 8);
// play_note(55*pow(2, 5/12.0), 4);
// play_note(55*pow(2, 3/12.0), 4);
// play_note(55*pow(2, 2/12.0), 16);
} }
void play_note(float freq, int length) { void send_freq(double freq, int vol) {
DDRB |= (1<<7); int duty = (((double)F_CPU) / freq);
PORTB &= ~(1<<7); ICR3 = duty; // Set max to the period
OCR3A = duty >> (0x10 - vol); // Set compare to half the period
}
void stop_all_notes() {
voices = 0;
TCCR3A = 0;
TCCR3B = 0;
frequency = 0;
volume = 0;
for (int i = 0; i < 8; i++) {
frequencies[i] = 0;
volumes[i] = 0;
}
}
void stop_note(double freq) {
for (int i = 7; i >= 0; i--) {
if (frequencies[i] == freq) {
frequencies[i] = 0;
volumes[i] = 0;
for (int j = i; (j < 7); j++) {
frequencies[j] = frequencies[j+1];
frequencies[j+1] = 0;
volumes[j] = volumes[j+1];
volumes[j+1] = 0;
}
}
}
voices--;
if (voices < 0)
voices = 0;
if (voices == 0) {
TCCR3A = 0;
TCCR3B = 0;
frequency = 0;
volume = 0;
} else {
double freq = frequencies[voices - 1];
int vol = volumes[voices - 1];
if (frequency < freq) {
sliding = true;
for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
send_freq(f, vol);
}
sliding = false;
} else if (frequency > freq) {
sliding = true;
for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
send_freq(f, vol);
}
sliding = false;
}
send_freq(freq, vol);
frequency = freq;
volume = vol;
}
}
void init_notes() {
// TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (1 << WGM10);
// TCCR1B = (1 << COM1B1) | (0 << COM1A0) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
// DDRC |= (1<<6);
// TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
// TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
// ICR3 = 0xFFFF;
// OCR3A = (int)((float)wave[i]*ICR3/RANGE); //go to next array element
// cli();
// /* Enable interrupt on timer2 == 127, with clk/8 prescaler. At 16MHz,
// this gives a timer interrupt at 15625Hz. */
// TIMSK3 = (1 << OCIE3A);
// /* clear/reset timer on match */
// // TCCR3A = 1<<WGM31 | 0<<WGM30; CTC mode, reset on match
// // TCCR3B = 0<<CS32 | 1<<CS31 | 0<<CS30; /* clk, /8 prescaler */
// TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
// TCCR3B = (0 << WGM33) | (0 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
// TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
// TCCR1B = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
// // SPCR = 0x50;
// // SPSR = 0x01;
// DDRC |= (1<<6);
// // ICR3 = 0xFFFF;
// // OCR3A=80;
// PORTC |= (1<<6);
// sei();
}
// #define highByte(c) ((c >> 8) & 0x00FF)
// #define lowByte(c) (c & 0x00FF)
ISR(TIMER3_COMPA_vect) {
if (ICR3 > 0 && !sliding) {
switch (position) {
case 0: {
int duty = (((double)F_CPU) / (frequency));
ICR3 = duty; // Set max to the period
OCR3A = duty >> 1; // Set compare to half the period
break;
}
case 1: {
int duty = (((double)F_CPU) / (frequency*2));
ICR3 = duty; // Set max to the period
OCR3A = duty >> 1; // Set compare to half the period
break;
}
case 2: {
int duty = (((double)F_CPU) / (frequency*3));
ICR3 = duty; // Set max to the period
OCR3A = duty >> 1; // Set compare to half the period
break;
}
}
position = (position + 1) % 3;
}
// /* OCR2A has been cleared, per TCCR2A above */
// // OCR3A = 127;
// // pos1 += incr1;
// // pos2 += incr2;
// // pos3 += incr3;
// // sample = sinewave[highByte(pos1)] + sinewave[highByte(pos2)] + sinewave[highByte(pos3)];
// // OCR3A = sample;
// OCR3A=pgm_read_byte(&sinewave[pos1]);
// pos1++;
// // PORTC &= ~(1<<6);
// /* buffered, 1x gain, active mode */
// // SPDR = highByte(sample) | 0x70;
// // while (!(SPSR & (1<<SPIF)));
// // SPDR = lowByte(sample);
// // while (!(SPSR & (1<<SPIF)));
// // PORTC |= (1<<6);
}
void play_note(double freq, int vol) {
if (freq > 0) { if (freq > 0) {
int frequency = 1000000/freq; DDRC |= (1<<6);
ICR1 = frequency; // Set max to the period
OCR1C = frequency >> 1; // Set compare to half the period
TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010; TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
}
for (int i = 0; i < length; i++) { if (frequency != 0) {
_delay_us(50000); if (frequency < freq) {
} for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
send_freq(f, vol);
TCCR1A &= ~(_BV(COM1C1)); }
} } else if (frequency > freq) {
for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
// This is called at 8000 Hz to load the next sample. send_freq(f, vol);
ISR(TIMER1_COMPA_vect) { }
if (sample >= sounddata_length) { }
if (sample == sounddata_length + lastSample) {
TIMSK1 &= ~_BV(OCIE1A);
// Disable the per-sample timer completely.
TCCR1B &= ~_BV(CS10);
} }
else { send_freq(freq, vol);
OCR1C = sounddata_length + lastSample - sample; frequency = freq;
} volume = vol;
}
else {
OCR1C = pgm_read_byte(&sounddata_data[sample]);
}
++sample; frequencies[voices] = frequency;
volumes[voices] = volume;
voices++;
}
// ICR3 = 0xFFFF;
// for (int i = 0; i < 10000; i++) {
// OCR3A = round((sin(i*freq)*.5)+.5)*0xFFFF;
// // _delay_us(50);
// }
// TCCR3A = 0;
// TCCR3B = 0;
} }
void play_notes() { // void note(int x, float length) {
// DDRC |= (1<<6);
// int t = (int)(440*pow(2,-x/12.0)); // starting note
// for (int y = 0; y < length*1000/t; y++) { // note length
// PORTC |= (1<<6);
// delay_us(t);
// PORTC &= ~(1<<6);
// delay_us(t);
// }
// PORTC &= ~(1<<6);
// }
// void true_note(float x, float y, float length) {
// Set up Timer 2 to do pulse width modulation on the speaker // for (uint32_t i = 0; i < length * 50; i++) {
// pin. // uint32_t v = (uint32_t) (round(sin(PI*2*i*640000*pow(2, x/12.0))*.5+1 + sin(PI*2*i*640000*pow(2, y/12.0))*.5+1) / 2 * pow(2, 8));
// for (int u = 0; u < 8; u++) {
DDRB |= (1<<7); // if (v & (1 << u) && !(PORTC&(1<<6)))
PORTB &= ~(1<<7); // PORTC |= (1<<6);
// else if (PORTC&(1<<6))
// Use internal clock (datasheet p.160) // PORTC &= ~(1<<6);
// ASSR &= ~(_BV(EXCLK) | _BV(AS2)); // }
// }
// Set fast PWM mode (p.157) // PORTC &= ~(1<<6);
TCCR1A |= _BV(WGM21) | _BV(WGM20); // }
TCCR1B &= ~_BV(WGM22);
// Do non-inverting PWM on pin OC2A (p.155)
// On the Arduino this is pin 11.
TCCR1A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
TCCR1A &= ~(_BV(COM2B1) | _BV(COM2B0));
// No prescaler (p.158)
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
// Set initial pulse width to the first sample.
OCR1A = pgm_read_byte(&sounddata_data[0]);
cli();
// Set CTC mode (Clear Timer on Compare Match) (p.133)
// Have to set OCR1A *after*, otherwise it gets reset to 0!
TCCR2B = (TCCR2B & ~_BV(WGM13)) | _BV(WGM12);
TCCR2A = TCCR2A & ~(_BV(WGM11) | _BV(WGM10));
// No prescaler (p.134)
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
// Set the compare register (OCR1A).
// OCR1A is a 16-bit register, so we have to do this with
// interrupts disabled to be safe.
// OCR2A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
OCR2A = 2000;
// Enable interrupt when TCNT1 == OCR1A (p.136)
TIMSK1 |= _BV(OCIE2A);
sample = 0;
sei();
}
void note(int x, float length) {
DDRB |= (1<<1);
int t = (int)(440*pow(2,-x/12.0)); // starting note
for (int y = 0; y < length*1000/t; y++) { // note length
PORTB |= (1<<1);
delay_us(t);
PORTB &= ~(1<<1);
delay_us(t);
}
PORTB &= ~(1<<1);
}
void true_note(float x, float y, float length) {
for (uint32_t i = 0; i < length * 50; i++) {
uint32_t v = (uint32_t) (round(sin(PI*2*i*640000*pow(2, x/12.0))*.5+1 + sin(PI*2*i*640000*pow(2, y/12.0))*.5+1) / 2 * pow(2, 8));
for (int u = 0; u < 8; u++) {
if (v & (1 << u) && !(PORTB&(1<<1)))
PORTB |= (1<<1);
else if (PORTB&(1<<1))
PORTB &= ~(1<<1);
}
}
PORTB &= ~(1<<1);
}

View File

@ -6,4 +6,7 @@
void note(int x, float length); void note(int x, float length);
void beeps(); void beeps();
void true_note(float x, float y, float length); void true_note(float x, float y, float length);
void play_note(float freq, int length); void play_note(double freq, int vol);
void stop_note(double freq);
void stop_all_notes();
void init_notes();

View File

@ -1,8 +1,8 @@
#include "extended_keymap_common.h" #include "extended_keymap_common.h"
#include "backlight.h" #include "backlight.h"
#include "action_layer.h" #include "action_layer.h"
#include "lufa.h"
#include "keymap_midi.h" #include "keymap_midi.h"
#include "beeps.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = { /* Qwerty */ [0] = { /* Qwerty */

View File

@ -20,37 +20,91 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <lufa.h> #include <lufa.h>
uint8_t starting_note = 0x0C; uint8_t starting_note = 0x0C;
int offset = 7;
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{ {
if (id != 0) { if (id != 0) {
if (record->event.pressed) { if (record->event.pressed) {
midi_send_noteon(&midi_device, opt, (id & 0xFF), 127); midi_send_noteon(&midi_device, opt, (id & 0xFF), 127);
} else { } else {
midi_send_noteoff(&midi_device, opt, (id & 0xFF), 127); midi_send_noteoff(&midi_device, opt, (id & 0xFF), 127);
} }
}
if (record->event.key.col == 11 && record->event.key.row == 4 && record->event.pressed) {
starting_note++;
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
} }
if (record->event.key.col == 8 && record->event.key.row == 4 && record->event.pressed) {
starting_note--; if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note++;
play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
return;
} else {
stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
stop_all_notes();
return;
}
}
if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note--;
play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
return;
} else {
stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
stop_all_notes();
return;
}
}
if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset++;
midi_send_cc(&midi_device, 0, 0x7B, 0); midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0); midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0); midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0); midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0); midi_send_cc(&midi_device, 4, 0x7B, 0);
stop_all_notes();
for (int i = 0; i <= 7; i++) {
play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
_delay_us(80000);
stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
_delay_us(8000);
}
return;
}
if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset--;
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
stop_all_notes();
for (int i = 0; i <= 7; i++) {
play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
_delay_us(80000);
stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
_delay_us(8000);
}
return;
} }
if (record->event.pressed) { if (record->event.pressed) {
midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); // midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
} else { } else {
midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
} }
} }

View File

@ -23,7 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define CHNL(note, channel) (note + (channel << 8)) #define CHNL(note, channel) (note + (channel << 8))
#define SCALE (int []){ 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24, 26, 28, 29, 31, 33, 35, 36} #define SCALE (int []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
#define N_CN1 (0x600C + (12 * -1) + 0 ) #define N_CN1 (0x600C + (12 * -1) + 0 )
#define N_CN1S (0x600C + (12 * -1) + 1 ) #define N_CN1S (0x600C + (12 * -1) + 1 )

View File

@ -3,7 +3,7 @@ PJRC_DIR = protocol/pjrc
SRC += $(BLUEFRUIT_DIR)/main.c \ SRC += $(BLUEFRUIT_DIR)/main.c \
$(BLUEFRUIT_DIR)/bluefruit.c \ $(BLUEFRUIT_DIR)/bluefruit.c \
serial_uart.c \ ../serial_uart.c \
$(PJRC_DIR)/pjrc.c \ $(PJRC_DIR)/pjrc.c \
$(PJRC_DIR)/usb_keyboard.c \ $(PJRC_DIR)/usb_keyboard.c \
$(PJRC_DIR)/usb_debug.c \ $(PJRC_DIR)/usb_debug.c \

View File

@ -2,20 +2,16 @@
Bluefruit Protocol for TMK firmware Bluefruit Protocol for TMK firmware
Author: Benjamin Gould, 2013 Author: Benjamin Gould, 2013
Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
@ -76,6 +72,13 @@ static void send_mouse(report_mouse_t *report);
static void send_system(uint16_t data); static void send_system(uint16_t data);
static void send_consumer(uint16_t data); static void send_consumer(uint16_t data);
void sendString(char string[], int length) {
for(int i = 0; i < length; i++) {
serial_send(string[i]);
}
}
static host_driver_t driver = { static host_driver_t driver = {
keyboard_leds, keyboard_leds,
send_keyboard, send_keyboard,
@ -100,6 +103,7 @@ static void send_keyboard(report_keyboard_t *report)
#endif #endif
bluefruit_serial_send(0xFD); bluefruit_serial_send(0xFD);
for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
bluefruit_serial_send(report->raw[i]); bluefruit_serial_send(report->raw[i]);
} }
#ifdef BLUEFRUIT_TRACE_SERIAL #ifdef BLUEFRUIT_TRACE_SERIAL
@ -198,5 +202,4 @@ static void send_consumer(uint16_t data)
#ifdef BLUEFRUIT_TRACE_SERIAL #ifdef BLUEFRUIT_TRACE_SERIAL
bluefruit_trace_footer(); bluefruit_trace_footer();
#endif #endif
} }

View File

@ -2,17 +2,14 @@
Bluefruit Protocol for TMK firmware Bluefruit Protocol for TMK firmware
Author: Benjamin Gould, 2013 Author: Benjamin Gould, 2013
Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -25,4 +22,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
host_driver_t *bluefruit_driver(void); host_driver_t *bluefruit_driver(void);
#endif #endif

View File

@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include <util/delay.h> #include <util/delay.h>
#include "serial.h" #include "../serial.h"
#include "keyboard.h" #include "keyboard.h"
#include "usb.h" #include "usb.h"
#include "host.h" #include "host.h"
@ -40,23 +40,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BLUEFRUIT_HOST_DRIVER 1 #define BLUEFRUIT_HOST_DRIVER 1
#define PJRC_HOST_DRIVER 2 #define PJRC_HOST_DRIVER 2
int main(void) int main(void)
{ {
CPU_PRESCALE(0); CPU_PRESCALE(0);
DDRD = _BV(PD5); // DDRD = _BV(PD5);
DDRB = _BV(PB0); // DDRB = _BV(PB0);
PORTD = _BV(PD5); // PORTD = _BV(PD5);
PORTB = _BV(PB0); // PORTB = _BV(PB0);
print_set_sendchar(sendchar); print_set_sendchar(sendchar);
usb_init(); // usb_init();
_delay_ms(2000); // _delay_ms(2000);
// while (!usb_configured()) /* wait */ // while (!usb_configured()) /* wait */
dprintf("Initializing keyboard...\n"); dprintf("Initializing keyboard...\n");
keyboard_init(); keyboard_init();
@ -64,53 +67,72 @@ int main(void)
// is not configured, choose the Bluefruit, otherwise use USB // is not configured, choose the Bluefruit, otherwise use USB
// Definitely would prefer to have this driven by an input pin and make // Definitely would prefer to have this driven by an input pin and make
// it switch dynamically - BCG // it switch dynamically - BCG
if (!usb_configured()) { // if (!usb_configured()) {
// Send power to Bluefruit... Adafruit says it takes 27 mA, I think // // 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 // // the pins should provide 40 mA, but just in case I switch the
// Bluefruit using a transistor - BCG // // Bluefruit using a transistor - BCG
DDRB = _BV(PB6); // DDRB = _BV(PB6);
PORTB |= _BV(PB6); // PORTB |= _BV(PB6);
dprintf("Setting host driver to bluefruit...\n"); dprintf("Setting host driver to bluefruit...\n");
host_set_driver(bluefruit_driver()); host_set_driver(bluefruit_driver());
dprintf("Initializing serial...\n"); dprintf("Initializing serial...\n");
serial_init(); serial_init();
// char swpa[] = "+++\r\n";
// for (int i = 0; i < 5; i++) {
// serial_send(swpa[i]);
// }
// char ble_enable[] = "AT+BLEKEYBOARDEN=1\r\n";
// for (int i = 0; i < 20; i++) {
// serial_send(ble_enable[i]);
// }
// char reset[] = "ATZ\r\n";
// for (int i = 0; i < 5; i++) {
// serial_send(reset[i]);
// }
// for (int i = 0; i < 5; i++) {
// serial_send(swpa[i]);
// }
// wait an extra second for the PC's operating system // wait an extra second for the PC's operating system
// to load drivers and do whatever it does to actually // to load drivers and do whatever it does to actually
// be ready for input // be ready for input
_delay_ms(1000); _delay_ms(1000);
PORTD = ~_BV(PD5); // PORTD = ~_BV(PD5);
dprintf("Starting main loop"); dprintf("Starting main loop");
while (1) { while (1) {
keyboard_task(); keyboard_task();
} }
} else { // } else {
// I'm not smart enough to get this done with LUFA - BCG // // I'm not smart enough to get this done with LUFA - BCG
dprintf("Setting host driver to PJRC...\n"); // dprintf("Setting host driver to PJRC...\n");
host_set_driver(pjrc_driver()); // host_set_driver(pjrc_driver());
#ifdef SLEEP_LED_ENABLE // #ifdef SLEEP_LED_ENABLE
sleep_led_init(); // sleep_led_init();
#endif // #endif
// wait an extra second for the PC's operating system // // wait an extra second for the PC's operating system
// to load drivers and do whatever it does to actually // // to load drivers and do whatever it does to actually
// be ready for input // // be ready for input
_delay_ms(1000); // _delay_ms(1000);
PORTB = ~_BV(PB0); // PORTB = ~_BV(PB0);
dprintf("Starting main loop"); // dprintf("Starting main loop");
while (1) { // while (1) {
while (suspend) { // while (suspend) {
suspend_power_down(); // suspend_power_down();
if (remote_wakeup && suspend_wakeup_condition()) { // if (remote_wakeup && suspend_wakeup_condition()) {
usb_remote_wakeup(); // usb_remote_wakeup();
} // }
} // }
keyboard_task(); // keyboard_task();
} // }
} // }
} }

View File

@ -266,7 +266,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP), .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100) .MaxPowerConsumption = USB_CONFIG_POWER_MA(500)
}, },
/* /*

View File

@ -840,13 +840,13 @@ int main(void)
/* wait for USB startup & debug output */ /* wait for USB startup & debug output */
// while (USB_DeviceState != DEVICE_STATE_Configured) { while (USB_DeviceState != DEVICE_STATE_Configured) {
// #if defined(INTERRUPT_CONTROL_ENDPOINT) // #if defined(INTERRUPT_CONTROL_ENDPOINT)
// ; // ;
// #else // #else
USB_USBTask(); USB_USBTask();
// #endif // #endif
// } }
print("USB configured.\n"); print("USB configured.\n");
/* init modules */ /* init modules */