$(COMMON_DIR)/print.c \ | $(COMMON_DIR)/print.c \ | ||||
$(COMMON_DIR)/debug.c \ | $(COMMON_DIR)/debug.c \ | ||||
$(COMMON_DIR)/bootloader.c \ | $(COMMON_DIR)/bootloader.c \ | ||||
$(COMMON_DIR)/bootmagic.c \ | |||||
$(COMMON_DIR)/eeconfig.c \ | $(COMMON_DIR)/eeconfig.c \ | ||||
$(COMMON_DIR)/util.c | $(COMMON_DIR)/util.c | ||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | #include <avr/io.h> | ||||
#include <avr/interrupt.h> | #include <avr/interrupt.h> | ||||
#include <avr/wdt.h> | |||||
#include <util/delay.h> | #include <util/delay.h> | ||||
#include "bootloader.h" | #include "bootloader.h" | ||||
/* Start Bootloader from Application | |||||
* See | |||||
* http://www.pjrc.com/teensy/jump_to_bootloader.html | |||||
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120219/html/_page__software_bootloader_start.html | |||||
*/ | |||||
#ifdef PROTOCOL_LUFA | |||||
#include <LUFA/Drivers/USB/USB.h> | |||||
#endif | |||||
// TODO: support usbasp | |||||
/* Boot Section Size in bytes | /* Boot Section Size in bytes | ||||
* Teensy halfKay 512 | * Teensy halfKay 512 | ||||
* Atmel DFU loader 4096 | * Atmel DFU loader 4096 | ||||
#ifndef BOOT_SIZE | #ifndef BOOT_SIZE | ||||
#define BOOT_SIZE 512 | #define BOOT_SIZE 512 | ||||
#endif | #endif | ||||
#define FLASH_SIZE (FLASHEND + 1) | #define FLASH_SIZE (FLASHEND + 1) | ||||
#define BOOTLOADER_START (FLASHEND - BOOT_SIZE) | |||||
#define BOOTLOADER_START (FLASH_SIZE - BOOT_SIZE) | |||||
/* | |||||
* Entering the Bootloader via Software | |||||
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html | |||||
*/ | |||||
#define BOOTLOADER_RESET_KEY 0xB007B007 | |||||
uint32_t reset_key __attribute__ ((section (".noinit"))); | |||||
/* initialize MCU status by watchdog reset */ | |||||
void bootloader_jump(void) { | void bootloader_jump(void) { | ||||
#ifdef PROTOCOL_LUFA | |||||
USB_Disable(); | |||||
cli(); | cli(); | ||||
_delay_ms(2000); | |||||
#endif | |||||
// | |||||
//Teensy | |||||
// | |||||
#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||||
// disable watchdog, if enabled | |||||
// disable all peripherals | |||||
#ifdef PROTOCOL_PJRC | |||||
cli(); | |||||
UDCON = 1; | UDCON = 1; | ||||
USBCON = (1<<FRZCLK); // disable USB | |||||
USBCON = (1<<FRZCLK); | |||||
UCSR1B = 0; | UCSR1B = 0; | ||||
_delay_ms(5); | _delay_ms(5); | ||||
#else | |||||
// This makes custom USBasploader come up. | |||||
MCUSR = 0; | |||||
#endif | #endif | ||||
// watchdog reset | |||||
reset_key = BOOTLOADER_RESET_KEY; | |||||
wdt_enable(WDTO_250MS); | |||||
for (;;); | |||||
} | |||||
/* this runs before main() */ | |||||
void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3"))); | |||||
void bootloader_jump_after_watchdog_reset(void) | |||||
{ | |||||
if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) { | |||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | |||||
// This makes custom USBasploader come up. | |||||
MCUSR = 0; | |||||
#endif | |||||
reset_key = 0; | |||||
((void (*)(void))BOOTLOADER_START)(); | |||||
} | |||||
} | |||||
#if 0 | |||||
/* Jumping To The Bootloader | |||||
* http://www.pjrc.com/teensy/jump_to_bootloader.html | |||||
* | |||||
* This method doen't work when using LUFA. idk why. | |||||
* - needs to initialize more regisers or interrupt setting? | |||||
*/ | |||||
void bootloader_jump(void) { | |||||
#ifdef PROTOCOL_LUFA | |||||
USB_Disable(); | |||||
cli(); | |||||
_delay_ms(2000); | |||||
#endif | |||||
#ifdef PROTOCOL_PJRC | |||||
cli(); | |||||
UDCON = 1; | |||||
USBCON = (1<<FRZCLK); | |||||
UCSR1B = 0; | |||||
_delay_ms(5); | |||||
#endif | |||||
/* | |||||
* Initialize | |||||
*/ | |||||
#if defined(__AVR_AT90USB162__) | #if defined(__AVR_AT90USB162__) | ||||
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; | EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; | ||||
TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0; | TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0; | ||||
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; | PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; | ||||
#endif | #endif | ||||
// | |||||
//USBasp | |||||
// | |||||
/* | |||||
* USBaspLoader | |||||
*/ | |||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | ||||
// This makes custom USBasploader come up. | // This makes custom USBasploader come up. | ||||
MCUSR = 0; | MCUSR = 0; | ||||
ADCSRA = 0; TWCR = 0; UCSR0B = 0; | ADCSRA = 0; TWCR = 0; UCSR0B = 0; | ||||
#endif | #endif | ||||
// start Bootloader | // start Bootloader | ||||
((void (*)(void))BOOTLOADER_START)(); | ((void (*)(void))BOOTLOADER_START)(); | ||||
} | } | ||||
#endif |
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <util/delay.h> | |||||
#include "matrix.h" | |||||
#include "keymap.h" | |||||
#include "eeconfig.h" | |||||
#include "bootloader.h" | |||||
#include "bootmagic.h" | |||||
void bootmagic(void) | |||||
{ | |||||
/* do scans in case of bounce */ | |||||
uint8_t scan = 100; | |||||
while (scan--) { matrix_scan(); _delay_ms(1); } | |||||
if (!BOOTMAGIC_IS_ENABLE()) { return; } | |||||
if (bootmagic_scan_keycode(BOOTMAGIC_BOOTLOADER_KEY)) { | |||||
bootloader_jump(); | |||||
} | |||||
if (bootmagic_scan_keycode(BOOTMAGIC_DEBUG_ENABLE_KEY)) { | |||||
eeconfig_write_debug(eeconfig_read_debug() ^ EECONFIG_DEBUG_ENABLE); | |||||
} | |||||
if (bootmagic_scan_keycode(BOOTMAGIC_EEPROM_CLEAR_KEY)) { | |||||
eeconfig_init(); | |||||
} | |||||
} | |||||
bool bootmagic_scan_keycode(uint8_t keycode) | |||||
{ | |||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | |||||
matrix_row_t matrix_row = matrix_get_row(r); | |||||
for (uint8_t c = 0; c < MATRIX_COLS; c++) { | |||||
if (matrix_row & ((matrix_row_t)1<<c)) { | |||||
if (keycode == keymap_key_to_keycode(0, (key_t){ .row = r, .col = c })) { | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return false; | |||||
} |
#ifndef BOOTMAGIC_H | |||||
#define BOOTMAGIC_H | |||||
#ifndef BOOTMAGIC_IS_ENABLE | |||||
#define BOOTMAGIC_IS_ENABLE() true | |||||
#endif | |||||
/* bootloader */ | |||||
#ifndef BOOTMAGIC_BOOTLOADER_KEY | |||||
#define BOOTMAGIC_BOOTLOADER_KEY KC_B | |||||
#endif | |||||
/* debug enable */ | |||||
#ifndef BOOTMAGIC_DEBUG_ENABLE_KEY | |||||
#define BOOTMAGIC_DEBUG_ENABLE_KEY KC_D | |||||
#endif | |||||
/* eeprom clear */ | |||||
#ifndef BOOTMAGIC_EEPROM_CLEAR_KEY | |||||
#define BOOTMAGIC_EEPROM_CLEAR_KEY KC_BSPACE | |||||
#endif | |||||
/* change default layer */ | |||||
#ifndef BOOTMAGIC_DEFAULT_LAYER_0_KEY | |||||
#define BOOTMAGIC_DEFAULT_LAYER_0_KEY KC_0 | |||||
#endif | |||||
#ifndef BOOTMAGIC_DEFAULT_LAYER_1_KEY | |||||
#define BOOTMAGIC_DEFAULT_LAYER_1_KEY KC_1 | |||||
#endif | |||||
#ifndef BOOTMAGIC_DEFAULT_LAYER_2_KEY | |||||
#define BOOTMAGIC_DEFAULT_LAYER_2_KEY KC_2 | |||||
#endif | |||||
#ifndef BOOTMAGIC_DEFAULT_LAYER_3_KEY | |||||
#define BOOTMAGIC_DEFAULT_LAYER_3_KEY KC_3 | |||||
#endif | |||||
void bootmagic(void); | |||||
bool bootmagic_scan_keycode(uint8_t keycode); | |||||
#endif |
print("v: print device version & info\n"); | print("v: print device version & info\n"); | ||||
print("t: print timer count\n"); | print("t: print timer count\n"); | ||||
print("s: print status\n"); | print("s: print status\n"); | ||||
print("e: print eeprom config\n"); | |||||
print("e: print eeprom boot config\n"); | |||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
print("n: toggle NKRO\n"); | print("n: toggle NKRO\n"); | ||||
#endif | #endif | ||||
{ | { | ||||
uint8_t eebyte; | uint8_t eebyte; | ||||
print("magic: "); print_hex16(eeprom_read_word((uint16_t)0)); print("\n"); | |||||
eebyte = eeconfig_read_debug(); | eebyte = eeconfig_read_debug(); | ||||
print("debug: "); print_hex8(eebyte); print("\n"); | print("debug: "); print_hex8(eebyte); print("\n"); | ||||
#include "command.h" | #include "command.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "sendchar.h" | #include "sendchar.h" | ||||
#include "bootloader.h" | |||||
#include "bootmagic.h" | |||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE | ||||
#include "mousekey.h" | #include "mousekey.h" | ||||
#endif | #endif | ||||
ps2_mouse_init(); | ps2_mouse_init(); | ||||
#endif | #endif | ||||
/* matrix scan for boot magic keys */ | |||||
#ifdef DEBOUNCE | |||||
uint8_t scan = DEBOUNCE * 2; | |||||
while (scan--) { matrix_scan(); _delay_ms(1); } | |||||
#else | |||||
matrix_scan(); | |||||
#endif | |||||
/* boot magic keys */ | |||||
#ifdef IS_BOOTMAGIC_BOOTLOADER | |||||
/* kick up bootloader */ | |||||
if (IS_BOOTMAGIC_BOOTLOADER()) bootloader_jump(); | |||||
#endif | |||||
#ifdef IS_BOOTMAGIC_DEBUG | |||||
if (IS_BOOTMAGIC_DEBUG()) { | |||||
eeconfig_write_debug(eeconfig_read_debug() ^ EECONFIG_DEBUG_ENABLE); | |||||
} | |||||
#endif | |||||
#ifdef IS_BOOTMAGIC_EEPROM_CLEAR | |||||
if (IS_BOOTMAGIC_EEPROM_CLEAR()) eeconfig_init(); | |||||
#endif | |||||
bootmagic(); | |||||
if (eeconfig_initialized()) { | if (eeconfig_initialized()) { | ||||
uint8_t config; | uint8_t config; | ||||
} else { | } else { | ||||
eeconfig_init(); | eeconfig_init(); | ||||
} | } | ||||
} | } | ||||
/* | /* |
if (layer < OVERLAYS_SIZE) { | if (layer < OVERLAYS_SIZE) { | ||||
return pgm_read_byte(&overlays[(layer)][(key.row)][(key.col)]); | return pgm_read_byte(&overlays[(layer)][(key.row)][(key.col)]); | ||||
} else { | } else { | ||||
debug("key_to_keycode: overlay "); debug_dec(layer); debug(" is invalid.\n"); | |||||
// XXX: this may cuaes bootlaoder_jump incositent fail. | |||||
//debug("key_to_keycode: overlay "); debug_dec(layer); debug(" is invalid.\n"); | |||||
return KC_TRANSPARENT; | return KC_TRANSPARENT; | ||||
} | } | ||||
} | } | ||||
if (layer < KEYMAPS_SIZE) { | if (layer < KEYMAPS_SIZE) { | ||||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); | return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); | ||||
} else { | } else { | ||||
// XXX: this may cuaes bootlaoder_jump incositent fail. | |||||
//debug("key_to_keycode: base "); debug_dec(layer); debug(" is invalid.\n"); | |||||
// fall back to layer 0 | // fall back to layer 0 | ||||
debug("key_to_keycode: base "); debug_dec(layer); debug(" is invalid.\n"); | |||||
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]); | return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]); | ||||
} | } | ||||
} | } |
OPT_DEFS += -DF_USB=$(F_USB)UL | OPT_DEFS += -DF_USB=$(F_USB)UL | ||||
OPT_DEFS += -DARCH=ARCH_$(ARCH) | OPT_DEFS += -DARCH=ARCH_$(ARCH) | ||||
OPT_DEFS += $(LUFA_OPTS) | OPT_DEFS += $(LUFA_OPTS) | ||||
OPT_DEFS += -DHOST_LUFA | |||||
# This indicates using LUFA stack | |||||
OPT_DEFS += -DPROTOCOL_LUFA |
PJRC_DIR = protocol/pjrc | PJRC_DIR = protocol/pjrc | ||||
OPT_DEFS += -DHOST_PJRC | |||||
SRC += $(PJRC_DIR)/main.c \ | SRC += $(PJRC_DIR)/main.c \ | ||||
$(PJRC_DIR)/pjrc.c \ | $(PJRC_DIR)/pjrc.c \ | ||||
$(PJRC_DIR)/usb_keyboard.c \ | $(PJRC_DIR)/usb_keyboard.c \ | ||||
# Search Path | # Search Path | ||||
VPATH += $(TOP_DIR)/$(PJRC_DIR) | VPATH += $(TOP_DIR)/$(PJRC_DIR) | ||||
# This indicates using LUFA stack | |||||
# TODO: remove HOST_PJRC | |||||
OPT_DEFS += -DHOST_PJRC | |||||
OPT_DEFS += -DPROTOCOL_PJRC | |||||