Squashed 'tmk_core/' changes from 57d27a8..08ce4c3
08ce4c3 Add update for chibios in README 30cac1d Merge remote-tracking branch 'flabbergast-tmk_keyboard/chibios' f218a38 core: Remove unused warning. Fix tmk_keyboard/#293 3e68807 Chibios: add more guards for transmitting (fix a deadlock bug). cecc807 core: Speed up compilation d01d959 Merge remote-tracking branch 'upstream/master' into chibios 8ff12ae Merge pull request #230 from jerryen/master 3afb83d core: Add note about sudo and git 2525d5d Chibios: Update to new USB API. 2fc5cd6 Merge branch 'master' into chibios 6f5511a core: Fix variable initialize 02a15fa core: Fix variable init and header include 1833ca1 Merge pull request #292 from obones/command_warning bc9dc6f Merge pull request #294 from shayneholmes/fix-debug-message c1b891b Merge pull request #295 from doopai/master 1da837c core: Add macro commands SM(), RM() and CM() d9d5a93 Add support for storing, restoring and clearing modifiers in macros 4f371c0 core: Add dfu-programmer example to doc/build.md ba3792e core: Fix doc/build.md 4b99fed remove SERIAL_SOFT_DEBUG macro 984accb Fix typo in bootmagic debug message 67a7ea1 usb_usb: Fix for keymap editor 2fc9ae4 host_driver is only used if KEYBOARD_LOCK_ENABLE is defined a35cdea Chibios: add 'core/protocol' to the makefiles' search path. 5ed2fd6 Merge remote-tracking branch 'upstream/master' into chibios bbc4851 Do timeout when writing to CONSOLE EP queue. 2450559 Remove an errant comma trailing the KC_ERAS macro alias 8465747 Merge pull request #270 from jeffgran/single-tap-toggle a37339a Merge pull request #271 from jeffgran/default-layer-toggle 8e732f7 core: Update doc/build.md and remove other_projects.md e47dc15 Workaround for compiler warnings when console disabled. 4184c52 Add maple mini code. b555238 core: Fix rules.mk for dfu target 26dacf4 add ACTION_DEFAULT_LAYER_TOGGLE to toggle a default layer on/off 83607d9 enable TAPPING_TOGGLE=1 to work correctly bef3089 Merge branch 'master' into chibios f7a55fd core: Fix debug print of usb_hid 1402f7d core: Add keycode KC_JPY for JIS 8e3a460 Chibios: Remove the wait in the main loop. 7d41746 ChibiOS: prettify/document sleep_led code. 235cdee ChibiOS: Update infinity bootloader code to match updated ChibiOS. 807bf1e Chibios: Add breathing sleep LED on Kinetis MCUs. ba3bf7c ChibiOS: make reset request more CMSISy. bf2ffd4 Add correct chibios/bootloader_jump for infinity KB. f5e03fd Chibios/usb_main: rename a variable for clarity. 63a330c Fix drop key stroke d8f5b06 Fix report size of boot protocol. 38abb50 ChibiOS/STM32: send remote wakeup. 6725650 ChibiOS/kinetis: sending remote wakeup. 69f6e54 Chibios: use WFI in idle. WIP suspend stuff. 02f044b Move chibios/cortex selection to local Makefiles. fa59dfa Rename chibios example keyboard. 5c060de Add eeprom support for chibios/kinetis. efd0044 Move declaration of keymap_config. 7196b24 Make bootmagic.c code portable (_delay_ms -> wait_ms). 37b15b2 Add missing #include to keymap.c. 31316e3 Merge branch 'master' into chibios 166f312 Fix chibios/usb_main GET_REPORT handing. 57ac6c2 Add ARM Teensies bootloader code. 1758086 Move STM32 bootloader address config to separate .h file. 03bb026 Rename some Makefile defines. 76ba6ac NKRO fixes. 06498f8 Update chibios README. db0a4f5 Add basic sleep_led for chibios. c3f930e Move AVR specific sleep_led.c into avr. 4069494 Fix bootloader-jump compiling. 9117f7b Small updates. 269cb85 Implement jump-to-bootloader. 7e81b34 Move chibios to tool. 923a892 Make usb_main more USB_DRIVER #define independent. aa054f0 Add ChibiOS support (USB stack + support files). 1e3e282 Modularity and gcc warnings fixes. 2f60ce0 Add KEYBOARD_LOCK_ENABLE to makefile git-subtree-dir: tmk_core git-subtree-split: 08ce4c3021d2ecd446c5b9a137aded65423d241e
This commit is contained in:
parent
fdc38ef3f9
commit
28203e909e
16
README.md
16
README.md
@ -5,6 +5,16 @@ This is a keyboard firmware library with some useful features for Atmel AVR and
|
||||
Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>
|
||||
|
||||
|
||||
Updates
|
||||
-------
|
||||
#### 2016/02/10
|
||||
flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios>. See [protocol/chibios/README.md](protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
|
||||
|
||||
#### 2015/04/22
|
||||
separated with TMK Keyboard Firmware Collection
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
These features can be used in your keyboard.
|
||||
@ -27,12 +37,6 @@ These features can be used in your keyboard.
|
||||
|
||||
|
||||
|
||||
Updates
|
||||
-------
|
||||
2015/04/22 separated with TMK Keyboard Firmware Collection
|
||||
|
||||
|
||||
|
||||
TMK Keyboard Firmware Collection
|
||||
--------------------------------
|
||||
Complete firmwares for various keyboards and protocol converters.
|
||||
|
11
common.mk
11
common.mk
@ -1,4 +1,4 @@
|
||||
COMMON_DIR = common
|
||||
COMMON_DIR = $(TMK_DIR)/common
|
||||
SRC += $(COMMON_DIR)/host.c \
|
||||
$(COMMON_DIR)/keyboard.c \
|
||||
$(COMMON_DIR)/action.c \
|
||||
@ -53,8 +53,12 @@ ifdef USB_6KRO_ENABLE
|
||||
OPT_DEFS += -DUSB_6KRO_ENABLE
|
||||
endif
|
||||
|
||||
ifdef KEYBOARD_LOCK_ENABLE
|
||||
OPT_DEFS += -DKEYBOARD_LOCK_ENABLE
|
||||
endif
|
||||
|
||||
ifdef SLEEP_LED_ENABLE
|
||||
SRC += $(COMMON_DIR)/sleep_led.c
|
||||
SRC += $(COMMON_DIR)/avr/sleep_led.c
|
||||
OPT_DEFS += -DSLEEP_LED_ENABLE
|
||||
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
|
||||
endif
|
||||
@ -77,7 +81,8 @@ ifdef KEYMAP_SECTION_ENABLE
|
||||
endif
|
||||
|
||||
# Version string
|
||||
OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
|
||||
VERSION := $(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
|
||||
OPT_DEFS += -DVERSION=$(VERSION)
|
||||
|
||||
|
||||
# Search Path
|
||||
|
@ -131,10 +131,17 @@ void process_action(keyrecord_t *record)
|
||||
case MODS_TAP_TOGGLE:
|
||||
if (event.pressed) {
|
||||
if (tap_count <= TAPPING_TOGGLE) {
|
||||
register_mods(mods);
|
||||
if (mods & get_mods()) {
|
||||
dprint("MODS_TAP_TOGGLE: toggle mods off\n");
|
||||
unregister_mods(mods);
|
||||
} else {
|
||||
dprint("MODS_TAP_TOGGLE: toggle mods on\n");
|
||||
register_mods(mods);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tap_count < TAPPING_TOGGLE) {
|
||||
dprint("MODS_TAP_TOGGLE: release : unregister_mods\n");
|
||||
unregister_mods(mods);
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ enum layer_pram_tap_op {
|
||||
#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
|
||||
/* Default Layer */
|
||||
#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer)/4, 1<<((layer)%4))
|
||||
#define ACTION_DEFAULT_LAYER_TOGGLE(layer) ACTION_DEFAULT_LAYER_BIT_XOR((layer)/4, 1<<((layer)%4))
|
||||
/* Layer Operation */
|
||||
#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on))
|
||||
#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer)
|
||||
|
@ -34,6 +34,8 @@ void action_macro_play(const macro_t *macro_p)
|
||||
macro_t macro = END;
|
||||
uint8_t interval = 0;
|
||||
|
||||
uint8_t mod_storage = 0;
|
||||
|
||||
if (!macro_p) return;
|
||||
while (true) {
|
||||
switch (MACRO_READ()) {
|
||||
@ -66,6 +68,17 @@ void action_macro_play(const macro_t *macro_p)
|
||||
interval = MACRO_READ();
|
||||
dprintf("INTERVAL(%u)\n", interval);
|
||||
break;
|
||||
case MOD_STORE:
|
||||
mod_storage = get_mods();
|
||||
break;
|
||||
case MOD_RESTORE:
|
||||
set_mods(mod_storage);
|
||||
send_keyboard_report();
|
||||
break;
|
||||
case MOD_CLEAR:
|
||||
clear_mods();
|
||||
send_keyboard_report();
|
||||
break;
|
||||
case 0x04 ... 0x73:
|
||||
dprintf("DOWN(%02X)\n", macro);
|
||||
register_code(macro);
|
||||
|
@ -64,6 +64,9 @@ enum macro_command_id{
|
||||
/* 0x74 - 0x83 */
|
||||
WAIT = 0x74,
|
||||
INTERVAL,
|
||||
MOD_STORE,
|
||||
MOD_RESTORE,
|
||||
MOD_CLEAR,
|
||||
|
||||
/* 0x84 - 0xf3 (reserved for keycode up) */
|
||||
|
||||
@ -82,6 +85,9 @@ enum macro_command_id{
|
||||
#define TYPE(key) DOWN(key), UP(key)
|
||||
#define WAIT(ms) WAIT, (ms)
|
||||
#define INTERVAL(ms) INTERVAL, (ms)
|
||||
#define STORE() MOD_STORE
|
||||
#define RESTORE() MOD_RESTORE
|
||||
#define CLEAR() MOD_CLEAR
|
||||
|
||||
/* key down */
|
||||
#define D(key) DOWN(KC_##key)
|
||||
@ -93,6 +99,12 @@ enum macro_command_id{
|
||||
#define W(ms) WAIT(ms)
|
||||
/* interval */
|
||||
#define I(ms) INTERVAL(ms)
|
||||
/* store modifier(s) */
|
||||
#define SM() STORE()
|
||||
/* restore modifier(s) */
|
||||
#define RM() RESTORE()
|
||||
/* clear modifier(s) */
|
||||
#define CM() CLEAR()
|
||||
|
||||
/* for backward comaptibility */
|
||||
#define MD(key) DOWN(KC_##key)
|
||||
|
@ -30,7 +30,6 @@ static bool process_tapping(keyrecord_t *record);
|
||||
static bool waiting_buffer_enq(keyrecord_t record);
|
||||
static void waiting_buffer_clear(void);
|
||||
static bool waiting_buffer_typed(keyevent_t event);
|
||||
static bool waiting_buffer_has_anykey_pressed(void);
|
||||
static void waiting_buffer_scan_tap(void);
|
||||
static void debug_tapping_key(void);
|
||||
static void debug_waiting_buffer(void);
|
||||
@ -257,7 +256,7 @@ bool process_tapping(keyrecord_t *keyp)
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
|
||||
if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n") {};
|
||||
process_action(keyp);
|
||||
return true;
|
||||
}
|
||||
@ -324,14 +323,6 @@ bool waiting_buffer_typed(keyevent_t event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool waiting_buffer_has_anykey_pressed(void)
|
||||
{
|
||||
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
|
||||
if (waiting_buffer[i].event.pressed) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* scan buffer for tapping */
|
||||
void waiting_buffer_scan_tap(void)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <util/delay.h>
|
||||
#include "wait.h"
|
||||
#include "matrix.h"
|
||||
#include "bootloader.h"
|
||||
#include "debug.h"
|
||||
@ -10,6 +10,7 @@
|
||||
#include "eeconfig.h"
|
||||
#include "bootmagic.h"
|
||||
|
||||
keymap_config_t keymap_config;
|
||||
|
||||
void bootmagic(void)
|
||||
{
|
||||
@ -19,9 +20,9 @@ void bootmagic(void)
|
||||
}
|
||||
|
||||
/* do scans in case of bounce */
|
||||
print("boogmagic scan: ... ");
|
||||
print("bootmagic scan: ... ");
|
||||
uint8_t scan = 100;
|
||||
while (scan--) { matrix_scan(); _delay_ms(10); }
|
||||
while (scan--) { matrix_scan(); wait_ms(10); }
|
||||
print("done.\n");
|
||||
|
||||
/* bootmagic skip */
|
||||
|
46
common/chibios/bootloader.c
Normal file
46
common/chibios/bootloader.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "bootloader.h"
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#ifdef STM32_BOOTLOADER_ADDRESS
|
||||
/* STM32 */
|
||||
|
||||
#if defined(STM32F0XX)
|
||||
/* This code should be checked whether it runs correctly on platforms */
|
||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
|
||||
extern uint32_t __ram0_end__;
|
||||
|
||||
void bootloader_jump(void) {
|
||||
*((unsigned long *)(SYMVAL(__ram0_end__) - 4)) = 0xDEADBEEF; // set magic flag => reset handler will jump into boot loader
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
#else /* defined(STM32F0XX) */
|
||||
#error Check that the bootloader code works on your platform and add it to bootloader.c!
|
||||
#endif /* defined(STM32F0XX) */
|
||||
|
||||
#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
|
||||
/* Kinetis */
|
||||
|
||||
#if defined(KIIBOHD_BOOTLOADER)
|
||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
|
||||
#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
|
||||
const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
|
||||
void bootloader_jump(void) {
|
||||
__builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
|
||||
// request reset
|
||||
SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
|
||||
}
|
||||
|
||||
#else /* defined(KIIBOHD_BOOTLOADER) */
|
||||
/* Default for Kinetis - expecting an ARM Teensy */
|
||||
void bootloader_jump(void) {
|
||||
chThdSleepMilliseconds(100);
|
||||
__BKPT(0);
|
||||
}
|
||||
#endif /* defined(KIIBOHD_BOOTLOADER) */
|
||||
|
||||
#else /* neither STM32 nor KINETIS */
|
||||
void bootloader_jump(void) {}
|
||||
#endif
|
551
common/chibios/eeconfig.c
Normal file
551
common/chibios/eeconfig.c
Normal file
@ -0,0 +1,551 @@
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "eeconfig.h"
|
||||
|
||||
/*************************************/
|
||||
/* Hardware backend */
|
||||
/* */
|
||||
/* Code from PJRC/Teensyduino */
|
||||
/*************************************/
|
||||
|
||||
/* Teensyduino Core Library
|
||||
* http://www.pjrc.com/teensy/
|
||||
* Copyright (c) 2013 PJRC.COM, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* 1. The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* 2. If the Software is incorporated into a build system that allows
|
||||
* selection among a list of target devices, then similar target
|
||||
* devices manufactured by PJRC.COM must be included in the list of
|
||||
* target devices and selectable in the same manner.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(K20x) /* chip selection */
|
||||
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
|
||||
|
||||
// The EEPROM is really RAM with a hardware-based backup system to
|
||||
// flash memory. Selecting a smaller size EEPROM allows more wear
|
||||
// leveling, for higher write endurance. If you edit this file,
|
||||
// set this to the smallest size your application can use. Also,
|
||||
// due to Freescale's implementation, writing 16 or 32 bit words
|
||||
// (aligned to 2 or 4 byte boundaries) has twice the endurance
|
||||
// compared to writing 8 bit bytes.
|
||||
//
|
||||
#define EEPROM_SIZE 32
|
||||
|
||||
// Writing unaligned 16 or 32 bit data is handled automatically when
|
||||
// this is defined, but at a cost of extra code size. Without this,
|
||||
// any unaligned write will cause a hard fault exception! If you're
|
||||
// absolutely sure all 16 and 32 bit writes will be aligned, you can
|
||||
// remove the extra unnecessary code.
|
||||
//
|
||||
#define HANDLE_UNALIGNED_WRITES
|
||||
|
||||
// Minimum EEPROM Endurance
|
||||
// ------------------------
|
||||
#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
|
||||
#define EEESIZE 0x33
|
||||
#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
|
||||
#define EEESIZE 0x34
|
||||
#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
|
||||
#define EEESIZE 0x35
|
||||
#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
|
||||
#define EEESIZE 0x36
|
||||
#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
|
||||
#define EEESIZE 0x37
|
||||
#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
|
||||
#define EEESIZE 0x38
|
||||
#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
|
||||
#define EEESIZE 0x39
|
||||
#endif
|
||||
|
||||
void eeprom_initialize(void)
|
||||
{
|
||||
uint32_t count=0;
|
||||
uint16_t do_flash_cmd[] = {
|
||||
0xf06f, 0x037f, 0x7003, 0x7803,
|
||||
0xf013, 0x0f80, 0xd0fb, 0x4770};
|
||||
uint8_t status;
|
||||
|
||||
if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
|
||||
// FlexRAM is configured as traditional RAM
|
||||
// We need to reconfigure for EEPROM usage
|
||||
FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
|
||||
FTFL->FCCOB4 = EEESIZE; // EEPROM Size
|
||||
FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
|
||||
__disable_irq();
|
||||
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
|
||||
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
|
||||
__enable_irq();
|
||||
status = FTFL->FSTAT;
|
||||
if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
|
||||
FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
|
||||
return; // error
|
||||
}
|
||||
}
|
||||
// wait for eeprom to become ready (is this really necessary?)
|
||||
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
|
||||
if (++count > 20000) break;
|
||||
}
|
||||
}
|
||||
|
||||
#define FlexRAM ((uint8_t *)0x14000000)
|
||||
|
||||
uint8_t eeprom_read_byte(const uint8_t *addr)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
if (offset >= EEPROM_SIZE) return 0;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
return FlexRAM[offset];
|
||||
}
|
||||
|
||||
uint16_t eeprom_read_word(const uint16_t *addr)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
if (offset >= EEPROM_SIZE-1) return 0;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
return *(uint16_t *)(&FlexRAM[offset]);
|
||||
}
|
||||
|
||||
uint32_t eeprom_read_dword(const uint32_t *addr)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
if (offset >= EEPROM_SIZE-3) return 0;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
return *(uint32_t *)(&FlexRAM[offset]);
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
uint8_t *dest = (uint8_t *)buf;
|
||||
uint32_t end = offset + len;
|
||||
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
if (end > EEPROM_SIZE) end = EEPROM_SIZE;
|
||||
while (offset < end) {
|
||||
*dest++ = FlexRAM[offset++];
|
||||
}
|
||||
}
|
||||
|
||||
int eeprom_is_ready(void)
|
||||
{
|
||||
return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void flexram_wait(void)
|
||||
{
|
||||
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
|
||||
// TODO: timeout
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t *addr, uint8_t value)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
|
||||
if (offset >= EEPROM_SIZE) return;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
if (FlexRAM[offset] != value) {
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint16_t *addr, uint16_t value)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
|
||||
if (offset >= EEPROM_SIZE-1) return;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
#ifdef HANDLE_UNALIGNED_WRITES
|
||||
if ((offset & 1) == 0) {
|
||||
#endif
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
|
||||
*(uint16_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
}
|
||||
#ifdef HANDLE_UNALIGNED_WRITES
|
||||
} else {
|
||||
if (FlexRAM[offset] != value) {
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
}
|
||||
if (FlexRAM[offset + 1] != (value >> 8)) {
|
||||
FlexRAM[offset + 1] = value >> 8;
|
||||
flexram_wait();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void eeprom_write_dword(uint32_t *addr, uint32_t value)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
|
||||
if (offset >= EEPROM_SIZE-3) return;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
#ifdef HANDLE_UNALIGNED_WRITES
|
||||
switch (offset & 3) {
|
||||
case 0:
|
||||
#endif
|
||||
if (*(uint32_t *)(&FlexRAM[offset]) != value) {
|
||||
*(uint32_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
}
|
||||
return;
|
||||
#ifdef HANDLE_UNALIGNED_WRITES
|
||||
case 2:
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
|
||||
*(uint16_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
}
|
||||
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
|
||||
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
|
||||
flexram_wait();
|
||||
}
|
||||
return;
|
||||
default:
|
||||
if (FlexRAM[offset] != value) {
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
}
|
||||
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
|
||||
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
|
||||
flexram_wait();
|
||||
}
|
||||
if (FlexRAM[offset + 3] != (value >> 24)) {
|
||||
FlexRAM[offset + 3] = value >> 24;
|
||||
flexram_wait();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
|
||||
if (offset >= EEPROM_SIZE) return;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
|
||||
if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
|
||||
while (len > 0) {
|
||||
uint32_t lsb = offset & 3;
|
||||
if (lsb == 0 && len >= 4) {
|
||||
// write aligned 32 bits
|
||||
uint32_t val32;
|
||||
val32 = *src++;
|
||||
val32 |= (*src++ << 8);
|
||||
val32 |= (*src++ << 16);
|
||||
val32 |= (*src++ << 24);
|
||||
if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
|
||||
*(uint32_t *)(&FlexRAM[offset]) = val32;
|
||||
flexram_wait();
|
||||
}
|
||||
offset += 4;
|
||||
len -= 4;
|
||||
} else if ((lsb == 0 || lsb == 2) && len >= 2) {
|
||||
// write aligned 16 bits
|
||||
uint16_t val16;
|
||||
val16 = *src++;
|
||||
val16 |= (*src++ << 8);
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
|
||||
*(uint16_t *)(&FlexRAM[offset]) = val16;
|
||||
flexram_wait();
|
||||
}
|
||||
offset += 2;
|
||||
len -= 2;
|
||||
} else {
|
||||
// write 8 bits
|
||||
uint8_t val8 = *src++;
|
||||
if (FlexRAM[offset] != val8) {
|
||||
FlexRAM[offset] = val8;
|
||||
flexram_wait();
|
||||
}
|
||||
offset++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void do_flash_cmd(volatile uint8_t *fstat)
|
||||
{
|
||||
*fstat = 0x80;
|
||||
while ((*fstat & 0x80) == 0) ; // wait
|
||||
}
|
||||
00000000 <do_flash_cmd>:
|
||||
0: f06f 037f mvn.w r3, #127 ; 0x7f
|
||||
4: 7003 strb r3, [r0, #0]
|
||||
6: 7803 ldrb r3, [r0, #0]
|
||||
8: f013 0f80 tst.w r3, #128 ; 0x80
|
||||
c: d0fb beq.n 6 <do_flash_cmd+0x6>
|
||||
e: 4770 bx lr
|
||||
*/
|
||||
|
||||
#elif defined(KL2x) /* chip selection */
|
||||
/* Teensy LC (emulated) */
|
||||
|
||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
|
||||
|
||||
extern uint32_t __eeprom_workarea_start__;
|
||||
extern uint32_t __eeprom_workarea_end__;
|
||||
|
||||
#define EEPROM_SIZE 128
|
||||
|
||||
static uint32_t flashend = 0;
|
||||
|
||||
void eeprom_initialize(void)
|
||||
{
|
||||
const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
|
||||
|
||||
do {
|
||||
if (*p++ == 0xFFFF) {
|
||||
flashend = (uint32_t)(p - 2);
|
||||
return;
|
||||
}
|
||||
} while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
|
||||
flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
|
||||
}
|
||||
|
||||
uint8_t eeprom_read_byte(const uint8_t *addr)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
|
||||
const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
|
||||
uint16_t val;
|
||||
uint8_t data=0xFF;
|
||||
|
||||
if (!end) {
|
||||
eeprom_initialize();
|
||||
end = (const uint16_t *)((uint32_t)flashend);
|
||||
}
|
||||
if (offset < EEPROM_SIZE) {
|
||||
while (p <= end) {
|
||||
val = *p++;
|
||||
if ((val & 255) == offset) data = val >> 8;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
|
||||
{
|
||||
// with great power comes great responsibility....
|
||||
uint32_t stat;
|
||||
*(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
|
||||
*(uint32_t *)&(FTFA->FCCOB7) = data;
|
||||
__disable_irq();
|
||||
(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
|
||||
__enable_irq();
|
||||
stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
|
||||
if (stat) {
|
||||
FTFA->FSTAT = stat;
|
||||
}
|
||||
MCM->PLACR |= MCM_PLACR_CFCC;
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t *addr, uint8_t data)
|
||||
{
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
|
||||
uint32_t i, val, flashaddr;
|
||||
uint16_t do_flash_cmd[] = {
|
||||
0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
|
||||
uint8_t buf[EEPROM_SIZE];
|
||||
|
||||
if (offset >= EEPROM_SIZE) return;
|
||||
if (!end) {
|
||||
eeprom_initialize();
|
||||
end = (const uint16_t *)((uint32_t)flashend);
|
||||
}
|
||||
if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
|
||||
val = (data << 8) | offset;
|
||||
flashaddr = (uint32_t)end;
|
||||
flashend = flashaddr;
|
||||
if ((flashaddr & 2) == 0) {
|
||||
val |= 0xFFFF0000;
|
||||
} else {
|
||||
val <<= 16;
|
||||
val |= 0x0000FFFF;
|
||||
}
|
||||
flash_write(do_flash_cmd, flashaddr, val);
|
||||
} else {
|
||||
for (i=0; i < EEPROM_SIZE; i++) {
|
||||
buf[i] = 0xFF;
|
||||
}
|
||||
for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
|
||||
val = *p;
|
||||
if ((val & 255) < EEPROM_SIZE) {
|
||||
buf[val & 255] = val >> 8;
|
||||
}
|
||||
}
|
||||
buf[offset] = data;
|
||||
for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
|
||||
*(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
|
||||
__disable_irq();
|
||||
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
|
||||
__enable_irq();
|
||||
val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
|
||||
if (val) FTFA->FSTAT = val;
|
||||
MCM->PLACR |= MCM_PLACR_CFCC;
|
||||
}
|
||||
flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
|
||||
for (i=0; i < EEPROM_SIZE; i++) {
|
||||
if (buf[i] == 0xFF) continue;
|
||||
if ((flashaddr & 2) == 0) {
|
||||
val = (buf[i] << 8) | i;
|
||||
} else {
|
||||
val = val | (buf[i] << 24) | (i << 16);
|
||||
flash_write(do_flash_cmd, flashaddr, val);
|
||||
}
|
||||
flashaddr += 2;
|
||||
}
|
||||
flashend = flashaddr;
|
||||
if ((flashaddr & 2)) {
|
||||
val |= 0xFFFF0000;
|
||||
flash_write(do_flash_cmd, flashaddr, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void do_flash_cmd(volatile uint8_t *fstat)
|
||||
{
|
||||
*fstat = 0x80;
|
||||
while ((*fstat & 0x80) == 0) ; // wait
|
||||
}
|
||||
00000000 <do_flash_cmd>:
|
||||
0: 2380 movs r3, #128 ; 0x80
|
||||
2: 7003 strb r3, [r0, #0]
|
||||
4: 7803 ldrb r3, [r0, #0]
|
||||
6: b25b sxtb r3, r3
|
||||
8: 2b00 cmp r3, #0
|
||||
a: dafb bge.n 4 <do_flash_cmd+0x4>
|
||||
c: 4770 bx lr
|
||||
*/
|
||||
|
||||
|
||||
uint16_t eeprom_read_word(const uint16_t *addr)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
|
||||
}
|
||||
|
||||
uint32_t eeprom_read_dword(const uint32_t *addr)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
|
||||
| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
uint8_t *dest = (uint8_t *)buf;
|
||||
while (len--) {
|
||||
*dest++ = eeprom_read_byte(p++);
|
||||
}
|
||||
}
|
||||
|
||||
int eeprom_is_ready(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint16_t *addr, uint16_t value)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p, value >> 8);
|
||||
}
|
||||
|
||||
void eeprom_write_dword(uint32_t *addr, uint32_t value)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p++, value >> 8);
|
||||
eeprom_write_byte(p++, value >> 16);
|
||||
eeprom_write_byte(p, value >> 24);
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
while (len--) {
|
||||
eeprom_write_byte(p++, *src++);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error EEPROM support not implemented for your chip
|
||||
#endif /* chip selection */
|
||||
|
||||
|
||||
/*****************/
|
||||
/* TMK functions */
|
||||
/*****************/
|
||||
|
||||
void eeconfig_init(void)
|
||||
{
|
||||
eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
|
||||
eeprom_write_byte(EECONFIG_DEBUG, 0);
|
||||
eeprom_write_byte(EECONFIG_DEFAULT_LAYER, 0);
|
||||
eeprom_write_byte(EECONFIG_KEYMAP, 0);
|
||||
eeprom_write_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
eeprom_write_byte(EECONFIG_BACKLIGHT, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void eeconfig_enable(void)
|
||||
{
|
||||
eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
void eeconfig_disable(void)
|
||||
{
|
||||
eeprom_write_word(EECONFIG_MAGIC, 0xFFFF);
|
||||
}
|
||||
|
||||
bool eeconfig_is_enabled(void)
|
||||
{
|
||||
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
|
||||
void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); }
|
||||
|
||||
uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
|
||||
void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); }
|
||||
|
||||
uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); }
|
||||
void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); }
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
|
||||
void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); }
|
||||
#endif
|
240
common/chibios/printf.c
Normal file
240
common/chibios/printf.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
|
||||
* and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
|
||||
*/
|
||||
|
||||
/*
|
||||
File: printf.c
|
||||
|
||||
Copyright (C) 2004 Kustaa Nyholm
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "printf.h"
|
||||
|
||||
typedef void (*putcf) (void*,char);
|
||||
static putcf stdout_putf;
|
||||
static void* stdout_putp;
|
||||
|
||||
// this adds cca 400 bytes
|
||||
#define PRINTF_LONG_SUPPORT
|
||||
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
|
||||
static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
|
||||
{
|
||||
int n=0;
|
||||
unsigned int d=1;
|
||||
while (num/d >= base)
|
||||
d*=base;
|
||||
while (d!=0) {
|
||||
int dgt = num / d;
|
||||
num%=d;
|
||||
d/=base;
|
||||
if (n || dgt>0|| d==0) {
|
||||
*bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
*bf=0;
|
||||
}
|
||||
|
||||
static void li2a (long num, char * bf)
|
||||
{
|
||||
if (num<0) {
|
||||
num=-num;
|
||||
*bf++ = '-';
|
||||
}
|
||||
uli2a(num,10,0,bf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
|
||||
{
|
||||
int n=0;
|
||||
unsigned int d=1;
|
||||
while (num/d >= base)
|
||||
d*=base;
|
||||
while (d!=0) {
|
||||
int dgt = num / d;
|
||||
num%= d;
|
||||
d/=base;
|
||||
if (n || dgt>0 || d==0) {
|
||||
*bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
*bf=0;
|
||||
}
|
||||
|
||||
static void i2a (int num, char * bf)
|
||||
{
|
||||
if (num<0) {
|
||||
num=-num;
|
||||
*bf++ = '-';
|
||||
}
|
||||
ui2a(num,10,0,bf);
|
||||
}
|
||||
|
||||
static int a2d(char ch)
|
||||
{
|
||||
if (ch>='0' && ch<='9')
|
||||
return ch-'0';
|
||||
else if (ch>='a' && ch<='f')
|
||||
return ch-'a'+10;
|
||||
else if (ch>='A' && ch<='F')
|
||||
return ch-'A'+10;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
static char a2i(char ch, char** src,int base,int* nump)
|
||||
{
|
||||
char* p= *src;
|
||||
int num=0;
|
||||
int digit;
|
||||
while ((digit=a2d(ch))>=0) {
|
||||
if (digit>base) break;
|
||||
num=num*base+digit;
|
||||
ch=*p++;
|
||||
}
|
||||
*src=p;
|
||||
*nump=num;
|
||||
return ch;
|
||||
}
|
||||
|
||||
static void putchw(void* putp,putcf putf,int n, char z, char* bf)
|
||||
{
|
||||
char fc=z? '0' : ' ';
|
||||
char ch;
|
||||
char* p=bf;
|
||||
while (*p++ && n > 0)
|
||||
n--;
|
||||
while (n-- > 0)
|
||||
putf(putp,fc);
|
||||
while ((ch= *bf++))
|
||||
putf(putp,ch);
|
||||
}
|
||||
|
||||
void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
|
||||
{
|
||||
char bf[12];
|
||||
|
||||
char ch;
|
||||
|
||||
|
||||
while ((ch=*(fmt++))) {
|
||||
if (ch!='%')
|
||||
putf(putp,ch);
|
||||
else {
|
||||
char lz=0;
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
char lng=0;
|
||||
#endif
|
||||
int w=0;
|
||||
ch=*(fmt++);
|
||||
if (ch=='0') {
|
||||
ch=*(fmt++);
|
||||
lz=1;
|
||||
}
|
||||
if (ch>='0' && ch<='9') {
|
||||
ch=a2i(ch,&fmt,10,&w);
|
||||
}
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
if (ch=='l') {
|
||||
ch=*(fmt++);
|
||||
lng=1;
|
||||
}
|
||||
#endif
|
||||
switch (ch) {
|
||||
case 0:
|
||||
goto abort;
|
||||
case 'u' : {
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
if (lng)
|
||||
uli2a(va_arg(va, unsigned long int),10,0,bf);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int),10,0,bf);
|
||||
putchw(putp,putf,w,lz,bf);
|
||||
break;
|
||||
}
|
||||
case 'd' : {
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
if (lng)
|
||||
li2a(va_arg(va, unsigned long int),bf);
|
||||
else
|
||||
#endif
|
||||
i2a(va_arg(va, int),bf);
|
||||
putchw(putp,putf,w,lz,bf);
|
||||
break;
|
||||
}
|
||||
case 'x': case 'X' :
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
if (lng)
|
||||
uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
|
||||
putchw(putp,putf,w,lz,bf);
|
||||
break;
|
||||
case 'c' :
|
||||
putf(putp,(char)(va_arg(va, int)));
|
||||
break;
|
||||
case 's' :
|
||||
putchw(putp,putf,w,0,va_arg(va, char*));
|
||||
break;
|
||||
case '%' :
|
||||
putf(putp,ch);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
abort:;
|
||||
}
|
||||
|
||||
|
||||
void init_printf(void* putp,void (*putf) (void*,char))
|
||||
{
|
||||
stdout_putf=putf;
|
||||
stdout_putp=putp;
|
||||
}
|
||||
|
||||
void tfp_printf(char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va,fmt);
|
||||
tfp_format(stdout_putp,stdout_putf,fmt,va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void putcp(void* p,char c)
|
||||
{
|
||||
*(*((char**)p))++ = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tfp_sprintf(char* s,char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va,fmt);
|
||||
tfp_format(&s,putcp,fmt,va);
|
||||
putcp(&s,0);
|
||||
va_end(va);
|
||||
}
|
111
common/chibios/printf.h
Normal file
111
common/chibios/printf.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
|
||||
* and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
|
||||
*/
|
||||
|
||||
/*
|
||||
File: printf.h
|
||||
|
||||
Copyright (C) 2004 Kustaa Nyholm
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
This library is realy just two files: 'printf.h' and 'printf.c'.
|
||||
|
||||
They provide a simple and small (+200 loc) printf functionality to
|
||||
be used in embedded systems.
|
||||
|
||||
I've found them so usefull in debugging that I do not bother with a
|
||||
debugger at all.
|
||||
|
||||
They are distributed in source form, so to use them, just compile them
|
||||
into your project.
|
||||
|
||||
Two printf variants are provided: printf and sprintf.
|
||||
|
||||
The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
|
||||
|
||||
Zero padding and field width are also supported.
|
||||
|
||||
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
|
||||
long specifier is also
|
||||
supported. Note that this will pull in some long math routines (pun intended!)
|
||||
and thus make your executable noticably longer.
|
||||
|
||||
The memory foot print of course depends on the target cpu, compiler and
|
||||
compiler options, but a rough guestimate (based on a H8S target) is about
|
||||
1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
|
||||
Not too bad. Your milage may vary. By hacking the source code you can
|
||||
get rid of some hunred bytes, I'm sure, but personally I feel the balance of
|
||||
functionality and flexibility versus code size is close to optimal for
|
||||
many embedded systems.
|
||||
|
||||
To use the printf you need to supply your own character output function,
|
||||
something like :
|
||||
|
||||
void putc ( void* p, char c)
|
||||
{
|
||||
while (!SERIAL_PORT_EMPTY) ;
|
||||
SERIAL_PORT_TX_REGISTER = c;
|
||||
}
|
||||
|
||||
Before you can call printf you need to initialize it to use your
|
||||
character output function with something like:
|
||||
|
||||
init_printf(NULL,putc);
|
||||
|
||||
Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
|
||||
the NULL (or any pointer) you pass into the 'init_printf' will eventually be
|
||||
passed to your 'putc' routine. This allows you to pass some storage space (or
|
||||
anything realy) to the character output function, if necessary.
|
||||
This is not often needed but it was implemented like that because it made
|
||||
implementing the sprintf function so neat (look at the source code).
|
||||
|
||||
The code is re-entrant, except for the 'init_printf' function, so it
|
||||
is safe to call it from interupts too, although this may result in mixed output.
|
||||
If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
|
||||
|
||||
The printf and sprintf functions are actually macros that translate to
|
||||
'tfp_printf' and 'tfp_sprintf'. This makes it possible
|
||||
to use them along with 'stdio.h' printf's in a single source file.
|
||||
You just need to undef the names before you include the 'stdio.h'.
|
||||
Note that these are not function like macros, so if you have variables
|
||||
or struct members with these names, things will explode in your face.
|
||||
Without variadic macros this is the best we can do to wrap these
|
||||
fucnction. If it is a problem just give up the macros and use the
|
||||
functions directly or rename them.
|
||||
|
||||
For further details see source code.
|
||||
|
||||
regs Kusti, 23.10.2004
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TFP_PRINTF__
|
||||
#define __TFP_PRINTF__
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void init_printf(void* putp,void (*putf) (void*,char));
|
||||
|
||||
void tfp_printf(char *fmt, ...);
|
||||
void tfp_sprintf(char* s,char *fmt, ...);
|
||||
|
||||
void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
|
||||
|
||||
#define printf tfp_printf
|
||||
#define sprintf tfp_sprintf
|
||||
|
||||
#endif
|
164
common/chibios/sleep_led.c
Normal file
164
common/chibios/sleep_led.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "led.h"
|
||||
#include "sleep_led.h"
|
||||
|
||||
#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
|
||||
/* All right, we go the "software" way: LP timer, toggle LED in interrupt.
|
||||
* Based on hasu's code for AVRs.
|
||||
*/
|
||||
|
||||
/* Breathing Sleep LED brighness(PWM On period) table
|
||||
* (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
|
||||
*
|
||||
* http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
|
||||
* (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
|
||||
*/
|
||||
static const uint8_t breathing_table[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
|
||||
15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
|
||||
255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
|
||||
15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Low Power Timer interrupt handler */
|
||||
OSAL_IRQ_HANDLER(KINETIS_LPTMR0_IRQ_VECTOR) {
|
||||
OSAL_IRQ_PROLOGUE();
|
||||
|
||||
/* Software PWM
|
||||
* timer:1111 1111 1111 1111
|
||||
* \_____/\/ \_______/____ count(0-255)
|
||||
* \ \______________ duration of step(4)
|
||||
* \__________________ index of step table(0-63)
|
||||
*/
|
||||
|
||||
// this works for cca 65536 irqs/sec
|
||||
static union {
|
||||
uint16_t row;
|
||||
struct {
|
||||
uint8_t count:8;
|
||||
uint8_t duration:2;
|
||||
uint8_t index:6;
|
||||
} pwm;
|
||||
} timer = { .row = 0 };
|
||||
|
||||
timer.row++;
|
||||
|
||||
// LED on
|
||||
if (timer.pwm.count == 0) {
|
||||
led_set(1<<USB_LED_CAPS_LOCK);
|
||||
}
|
||||
// LED off
|
||||
if (timer.pwm.count == breathing_table[timer.pwm.index]) {
|
||||
led_set(0);
|
||||
}
|
||||
|
||||
/* Reset the counter */
|
||||
LPTMR0->CSR |= LPTMRx_CSR_TCF;
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/* LPTMR clock options */
|
||||
#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
|
||||
#define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
|
||||
#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
|
||||
#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
|
||||
|
||||
/* Work around inconsistencies in Freescale naming */
|
||||
#if !defined(SIM_SCGC5_LPTMR)
|
||||
#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
|
||||
#endif
|
||||
|
||||
/* Initialise the timer */
|
||||
void sleep_led_init(void) {
|
||||
/* Make sure the clock to the LPTMR is enabled */
|
||||
SIM->SCGC5 |= SIM_SCGC5_LPTMR;
|
||||
/* Reset LPTMR settings */
|
||||
LPTMR0->CSR = 0;
|
||||
/* Set the compare value */
|
||||
LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
|
||||
|
||||
/* Set up clock source and prescaler */
|
||||
/* Software PWM
|
||||
* ______ ______ __
|
||||
* | ON |___OFF___| ON |___OFF___| ....
|
||||
* |<-------------->|<-------------->|<- ....
|
||||
* PWM period PWM period
|
||||
*
|
||||
* R interrupts/period[resolution]
|
||||
* F periods/second[frequency]
|
||||
* R * F interrupts/second
|
||||
*/
|
||||
|
||||
/* === OPTION 1 === */
|
||||
#if 0
|
||||
// 1kHz LPO
|
||||
// No prescaler => 1024 irqs/sec
|
||||
// Note: this is too slow for a smooth breathe
|
||||
LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
|
||||
#endif /* OPTION 1 */
|
||||
|
||||
/* === OPTION 2 === */
|
||||
#if 1
|
||||
// nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
|
||||
MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
|
||||
#if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
|
||||
MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
|
||||
#endif /* KL27 */
|
||||
MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
|
||||
// to work in stop mode, also MCG_C1_IREFSTEN
|
||||
// Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
|
||||
// => approx F=61, R=256, duration = 4
|
||||
LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6);
|
||||
#endif /* OPTION 2 */
|
||||
|
||||
/* === OPTION 3 === */
|
||||
#if 0
|
||||
// OSC output (external crystal), usually 8MHz or 16MHz
|
||||
OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
|
||||
// to work in stop mode, also OSC_CR_EREFSTEN
|
||||
// Divide by 2^N
|
||||
LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
|
||||
#endif /* OPTION 3 */
|
||||
/* === END OPTIONS === */
|
||||
|
||||
/* Interrupt on TCF set (compare flag) */
|
||||
nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
|
||||
LPTMR0->CSR |= LPTMRx_CSR_TIE;
|
||||
}
|
||||
|
||||
void sleep_led_enable(void) {
|
||||
/* Enable the timer */
|
||||
LPTMR0->CSR |= LPTMRx_CSR_TEN;
|
||||
}
|
||||
|
||||
void sleep_led_disable(void) {
|
||||
/* Disable the timer */
|
||||
LPTMR0->CSR &= ~LPTMRx_CSR_TEN;
|
||||
}
|
||||
|
||||
void sleep_led_toggle(void) {
|
||||
/* Toggle the timer */
|
||||
LPTMR0->CSR ^= LPTMRx_CSR_TEN;
|
||||
}
|
||||
|
||||
#else /* platform selection: not on familiar Kinetis chips */
|
||||
|
||||
void sleep_led_init(void) {
|
||||
}
|
||||
|
||||
void sleep_led_enable(void) {
|
||||
led_set(1<<USB_LED_CAPS_LOCK);
|
||||
}
|
||||
|
||||
void sleep_led_disable(void) {
|
||||
led_set(0);
|
||||
}
|
||||
|
||||
void sleep_led_toggle(void) {
|
||||
// not implemented
|
||||
}
|
||||
|
||||
#endif /* platform selection */
|
65
common/chibios/suspend.c
Normal file
65
common/chibios/suspend.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* TODO */
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "matrix.h"
|
||||
#include "action.h"
|
||||
#include "action_util.h"
|
||||
#include "mousekey.h"
|
||||
#include "host.h"
|
||||
#include "backlight.h"
|
||||
#include "suspend.h"
|
||||
|
||||
void suspend_idle(uint8_t time) {
|
||||
// TODO: this is not used anywhere - what units is 'time' in?
|
||||
chThdSleepMilliseconds(time);
|
||||
}
|
||||
|
||||
void suspend_power_down(void) {
|
||||
// TODO: figure out what to power down and how
|
||||
// shouldn't power down TPM/FTM if we want a breathing LED
|
||||
// also shouldn't power down USB
|
||||
|
||||
// on AVR, this enables the watchdog for 15ms (max), and goes to
|
||||
// SLEEP_MODE_PWR_DOWN
|
||||
|
||||
chThdSleepMilliseconds(17);
|
||||
}
|
||||
|
||||
__attribute__ ((weak)) void matrix_power_up(void) {}
|
||||
__attribute__ ((weak)) void matrix_power_down(void) {}
|
||||
bool suspend_wakeup_condition(void)
|
||||
{
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// run immediately after wakeup
|
||||
void suspend_wakeup_init(void)
|
||||
{
|
||||
// clear keyboard state
|
||||
// need to do it manually, because we're running from ISR
|
||||
// and clear_keyboard() calls print
|
||||
// so only clear the variables in memory
|
||||
// the reports will be sent from main.c afterwards
|
||||
// or if the PC asks for GET_REPORT
|
||||
clear_mods();
|
||||
clear_weak_mods();
|
||||
clear_keys();
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
mousekey_clear();
|
||||
#endif /* MOUSEKEY_ENABLE */
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
host_system_send(0);
|
||||
host_consumer_send(0);
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
backlight_init();
|
||||
#endif /* BACKLIGHT_ENABLE */
|
||||
}
|
27
common/chibios/timer.c
Normal file
27
common/chibios/timer.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "ch.h"
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
void timer_init(void) {}
|
||||
|
||||
void timer_clear(void) {}
|
||||
|
||||
uint16_t timer_read(void)
|
||||
{
|
||||
return (uint16_t)ST2MS(chVTGetSystemTime());
|
||||
}
|
||||
|
||||
uint32_t timer_read32(void)
|
||||
{
|
||||
return ST2MS(chVTGetSystemTime());
|
||||
}
|
||||
|
||||
uint16_t timer_elapsed(uint16_t last)
|
||||
{
|
||||
return (uint16_t)(ST2MS(chVTTimeElapsedSinceX(MS2ST(last))));
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed32(uint32_t last)
|
||||
{
|
||||
return ST2MS(chVTTimeElapsedSinceX(MS2ST(last)));
|
||||
}
|
@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <util/delay.h>
|
||||
#include "wait.h"
|
||||
#include "keycode.h"
|
||||
#include "host.h"
|
||||
#include "keymap.h"
|
||||
@ -97,12 +97,14 @@ bool command_proc(uint8_t code)
|
||||
bool command_extra(uint8_t code) __attribute__ ((weak));
|
||||
bool command_extra(uint8_t code)
|
||||
{
|
||||
(void)code;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool command_console_extra(uint8_t code) __attribute__ ((weak));
|
||||
bool command_console_extra(uint8_t code)
|
||||
{
|
||||
(void)code;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -178,7 +180,9 @@ static void print_eeconfig(void)
|
||||
|
||||
static bool command_common(uint8_t code)
|
||||
{
|
||||
#ifdef KEYBOARD_LOCK_ENABLE
|
||||
static host_driver_t *host_driver = 0;
|
||||
#endif
|
||||
switch (code) {
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
case KC_Z:
|
||||
@ -223,7 +227,7 @@ static bool command_common(uint8_t code)
|
||||
case KC_PAUSE:
|
||||
clear_keyboard();
|
||||
print("\n\nbootloader... ");
|
||||
_delay_ms(1000);
|
||||
wait_ms(1000);
|
||||
bootloader_jump(); // not return
|
||||
break;
|
||||
case KC_D:
|
||||
@ -283,6 +287,9 @@ static bool command_common(uint8_t code)
|
||||
#ifdef PROTOCOL_VUSB
|
||||
" VUSB"
|
||||
#endif
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
" CHIBIOS"
|
||||
#endif
|
||||
#ifdef BOOTMAGIC_ENABLE
|
||||
" BOOTMAGIC"
|
||||
#endif
|
||||
@ -307,8 +314,13 @@ static bool command_common(uint8_t code)
|
||||
" " STR(BOOTLOADER_SIZE) "\n");
|
||||
|
||||
print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
|
||||
#if defined(__AVR__)
|
||||
" AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
|
||||
" AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
|
||||
#elif defined(__arm__)
|
||||
// TODO
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
case KC_S:
|
||||
print("\n\t- Status -\n");
|
||||
@ -318,7 +330,7 @@ static bool command_common(uint8_t code)
|
||||
#ifdef NKRO_ENABLE
|
||||
print_val_hex8(keyboard_nkro);
|
||||
#endif
|
||||
print_val_hex32(timer_count);
|
||||
print_val_hex32(timer_read32());
|
||||
|
||||
#ifdef PROTOCOL_PJRC
|
||||
print_val_hex8(UDCON);
|
||||
@ -338,10 +350,11 @@ static bool command_common(uint8_t code)
|
||||
case KC_N:
|
||||
clear_keyboard(); //Prevents stuck keys.
|
||||
keyboard_nkro = !keyboard_nkro;
|
||||
if (keyboard_nkro)
|
||||
if (keyboard_nkro) {
|
||||
print("NKRO: on\n");
|
||||
else
|
||||
} else {
|
||||
print("NKRO: off\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case KC_ESC:
|
||||
@ -595,10 +608,11 @@ static bool mousekey_console(uint8_t code)
|
||||
print("?");
|
||||
return false;
|
||||
}
|
||||
if (mousekey_param)
|
||||
if (mousekey_param) {
|
||||
xprintf("M%d> ", mousekey_param);
|
||||
else
|
||||
} else {
|
||||
print("M>" );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -85,15 +85,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define KC_LCAP KC_LOCKING_CAPS
|
||||
#define KC_LNUM KC_LOCKING_NUM
|
||||
#define KC_LSCR KC_LOCKING_SCROLL
|
||||
#define KC_ERAS KC_ALT_ERASE,
|
||||
#define KC_ERAS KC_ALT_ERASE
|
||||
#define KC_CLR KC_CLEAR
|
||||
/* Japanese specific */
|
||||
#define KC_ZKHK KC_GRAVE
|
||||
#define KC_RO KC_INT1
|
||||
#define KC_KANA KC_INT2
|
||||
#define KC_JYEN KC_INT3
|
||||
#define KC_JPY KC_INT3
|
||||
#define KC_HENK KC_INT4
|
||||
#define KC_MHEN KC_INT5
|
||||
/* Korean specific */
|
||||
#define KC_HAEN KC_LANG1
|
||||
#define KC_HANJ KC_LANG2
|
||||
/* Keypad */
|
||||
#define KC_P1 KC_KP_1
|
||||
#define KC_P2 KC_KP_2
|
||||
@ -113,6 +117,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define KC_PPLS KC_KP_PLUS
|
||||
#define KC_PEQL KC_KP_EQUAL
|
||||
#define KC_PENT KC_KP_ENTER
|
||||
/* Unix function key */
|
||||
#define KC_EXEC KC_EXECUTE
|
||||
#define KC_SLCT KC_SELECT
|
||||
#define KC_AGIN KC_AGAIN
|
||||
#define KC_PSTE KC_PASTE
|
||||
/* Mousekey */
|
||||
#define KC_MS_U KC_MS_UP
|
||||
#define KC_MS_D KC_MS_DOWN
|
||||
|
@ -22,7 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "action_macro.h"
|
||||
#include "wait.h"
|
||||
#include "debug.h"
|
||||
#include "bootloader.h"
|
||||
|
||||
#ifdef BOOTMAGIC_ENABLE
|
||||
extern keymap_config_t keymap_config;
|
||||
#endif
|
||||
|
||||
static action_t keycode_to_action(uint8_t keycode);
|
||||
|
||||
@ -109,6 +113,9 @@ action_t action_for_key(uint8_t layer, keypos_t key)
|
||||
__attribute__ ((weak))
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
(void)record;
|
||||
(void)id;
|
||||
(void)opt;
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
@ -116,6 +123,9 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
__attribute__ ((weak))
|
||||
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
(void)record;
|
||||
(void)id;
|
||||
(void)opt;
|
||||
}
|
||||
|
||||
|
||||
@ -123,7 +133,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
/* translates keycode to action */
|
||||
static action_t keycode_to_action(uint8_t keycode)
|
||||
{
|
||||
action_t action;
|
||||
action_t action = {};
|
||||
switch (keycode) {
|
||||
case KC_A ... KC_EXSEL:
|
||||
case KC_LCTRL ... KC_RGUI:
|
||||
|
@ -38,7 +38,6 @@ typedef union {
|
||||
bool nkro:1;
|
||||
};
|
||||
} keymap_config_t;
|
||||
keymap_config_t keymap_config;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -18,7 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef NODEBUG_H
|
||||
#define NODEBUG_H 1
|
||||
|
||||
#if !defined(NO_DEBUG)
|
||||
#define NO_DEBUG
|
||||
#endif
|
||||
#include "debug.h"
|
||||
#undef NO_DEBUG
|
||||
|
||||
|
@ -38,11 +38,15 @@ void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
|
||||
xdev_out(sendchar_func);
|
||||
}
|
||||
|
||||
#elif defined(__arm__)
|
||||
#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
|
||||
|
||||
// don't need anything extra
|
||||
|
||||
#elif defined(__arm__) /* __AVR__ */
|
||||
|
||||
// TODO
|
||||
//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
|
||||
|
||||
#endif
|
||||
#endif /* __AVR__ */
|
||||
|
||||
#endif
|
||||
|
@ -47,7 +47,15 @@ extern "C"
|
||||
/* function pointer of sendchar to be used by print utility */
|
||||
void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
||||
|
||||
#elif defined(__arm__)
|
||||
#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
|
||||
|
||||
#include "chibios/printf.h"
|
||||
|
||||
#define print(s) printf(s)
|
||||
#define println(s) printf(s "\r\n")
|
||||
#define xprintf printf
|
||||
|
||||
#elif defined(__arm__) /* __AVR__ */
|
||||
|
||||
#include "mbed/xprintf.h"
|
||||
|
||||
@ -91,9 +99,9 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
||||
|
||||
#else /* NO_PRINT */
|
||||
|
||||
#define xprintf
|
||||
#define print
|
||||
#define println
|
||||
#define xprintf(s,...)
|
||||
#define print(s)
|
||||
#define println(s)
|
||||
#define print_set_sendchar(func)
|
||||
#define print_dec(data)
|
||||
#define print_decs(data)
|
||||
@ -119,6 +127,7 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
||||
#define print_val_bin_reverse8(v)
|
||||
#define print_val_bin_reverse16(v)
|
||||
#define print_val_bin_reverse32(v)
|
||||
#define init_printf(s,ss)
|
||||
|
||||
#endif /* NO_PRINT */
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
# include <avr/pgmspace.h>
|
||||
#elif defined(__arm__)
|
||||
# define PROGMEM
|
||||
# define pgm_read_byte(p) *(p)
|
||||
# define pgm_read_word(p) *(p)
|
||||
# define pgm_read_byte(p) *((unsigned char*)p)
|
||||
# define pgm_read_word(p) *((uint16_t*)p)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -84,6 +84,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
|
||||
# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
|
||||
# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
|
||||
#elif defined(PROTOCOL_CHIBIOS) && defined(NKRO_ENABLE)
|
||||
# include "protocol/chibios/usb_main.h"
|
||||
# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
|
||||
# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
|
||||
# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
|
||||
|
||||
#else
|
||||
# define KEYBOARD_REPORT_SIZE 8
|
||||
|
@ -9,9 +9,13 @@ extern "C" {
|
||||
# include <util/delay.h>
|
||||
# define wait_ms(ms) _delay_ms(ms)
|
||||
# define wait_us(us) _delay_us(us)
|
||||
#elif defined(__arm__)
|
||||
#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
|
||||
# include "ch.h"
|
||||
# define wait_ms(ms) chThdSleepMilliseconds(ms)
|
||||
# define wait_us(us) chThdSleepMicroseconds(us)
|
||||
#elif defined(__arm__) /* __AVR__ */
|
||||
# include "wait_api.h"
|
||||
#endif
|
||||
#endif /* __AVR__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
64
doc/build.md
64
doc/build.md
@ -6,11 +6,11 @@ Download and Install
|
||||
--------------------
|
||||
### 1. Install Tools
|
||||
|
||||
1. **Toolchain** On Windows install [MHV AVR Tools][mhv] for AVR GCC compiler and [Cygwin][cygwin](or [MinGW][mingw]) for shell terminal. On Mac you can use [CrossPack][crosspack]. On Linux you can install AVR GCC with your favorite package manager.
|
||||
1. **Toolchain** On Windows install [Atmel AVR Toolchain][atmelgcc] for AVR GCC compiler and [Cygwin][cygwin](or [MinGW][mingw]) for shell terminal. On Mac you can use [CrossPack][crosspack] or your favorite package manager. On Linux you can install AVR GCC with your favorite package manager.
|
||||
|
||||
2. **Programmer** On Windows install [Atmel FLIP][flip]. On Mac and Linux install [dfu-programmer][dfu-prog].
|
||||
2. **Programmer** Install [dfu-programmer][dfu-prog]. GUI tool [Atmel FLIP][flip] also can be used on Windows.
|
||||
|
||||
3. **Driver** On Windows you start DFU bootloader on the chip first time you will see 'Found New Hardware Wizard' to install driver. If you install device driver properly you can find chip name like 'ATmega32U4' under 'LibUSB-Win32 Devices' tree on 'Device Manager'. If not you shall need to update its driver on 'Device Manager'. You will find the driver in `FLIP` install directory like: C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\. In case of `dfu-programmer` use its driver.
|
||||
3. **Driver** On Windows when you start DFU bootloader on the chip first time you will see **Found New Hardware Wizard** to install driver. If you install device driver properly you will find chip name like **ATmega32U4** under **LibUSB-Win32 Devices** tree on **Device Manager**. If not you shall need to update its driver on **Device Manager**. You will find the driver in `FLIP` install directory like: `C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\`. In case of `dfu-programmer` install driver distributed with it.
|
||||
|
||||
If you use PJRC Teensy you don't need step 2 and 3 above, just get [Teensy loader][teensy-loader].
|
||||
|
||||
@ -20,7 +20,7 @@ You can find firmware source at github:
|
||||
|
||||
- <https://github.com/tmk/tmk_keyboard>
|
||||
|
||||
If you are familiar with `Git` tools you are recommended to use it but you can also download zip archive from:
|
||||
If you are familiar with [`git`][git] tools you are recommended to use it but you can also download zip archive from:
|
||||
|
||||
- <https://github.com/tmk/tmk_keyboard/archive/master.zip>
|
||||
|
||||
@ -28,7 +28,7 @@ If you are familiar with `Git` tools you are recommended to use it but you can a
|
||||
Build firmware
|
||||
--------------
|
||||
### 1. Open terminal
|
||||
Open terminal window to get access to commands. Use Cygwin(or MingGW) `shell terminal` in Windows or `Terminal.app` on Mac OSX. In Windows press `Windows` key and `R` then enter `cmd` in 'Run command' dialog showing up.
|
||||
Open terminal window to get access to commands. Use Cygwin(or MingGW) shell terminal in Windows or `Terminal.app` on Mac OSX.
|
||||
|
||||
### 2. Change directory
|
||||
Move to project directory in the firmware source.
|
||||
@ -53,60 +53,65 @@ Now you have **hex** file to program on current directory. This **hex** is only
|
||||
How to program controller depends on controller chip and its board design. To program AVR USB chips you'll need to start it up in bootloader mode. Most of boards with the chip have a push button to let bootloader come up. Consult with your controller board manual.
|
||||
|
||||
### 2. Program with DFU bootloader
|
||||
Stock AVR USB chip including ATmega32U4 has DFU bootloader by factory default. `FLIP` is a DFU programmer on Windows offered by Atmel. Open source command line tool `dfu-programmer` also supports AVR chips, it runs on Linux, Mac OSX and even Windows.
|
||||
Stock AVR USB chips have DFU bootloader by factory default. `FLIP` is a DFU programmer on Windows offered by Atmel. `FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial below. Open source alternative `dfu-programmer` also supports AVR chips, it is command line tool and runs on Linux, Mac OSX and even Windows.
|
||||
|
||||
To program AVR chip with DFU bootloader use `FLIP` or `dfu-programmer`.
|
||||
If you have a proper program command in `Makefile` just type this.
|
||||
|
||||
`FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial below.
|
||||
To use command line tool run this command. Note that you need to set PATH variable properly.
|
||||
To program with command of `FLIP` run this. Note that you need to set PATH variable properly.
|
||||
|
||||
$ make -f Makefile.<variant> flip
|
||||
|
||||
Or to program with `dfu-programmer` run:
|
||||
With `dfu-programmer` run this.
|
||||
|
||||
$ make -f Makefile.<variant> dfu
|
||||
|
||||
#### FLIP GUI tutorial
|
||||
1. On menu bar click Device -> Select, then. `ATmega32u4`.
|
||||
2. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog.
|
||||
At this point you'll see grey-outed widgets on the app get colored and ready.
|
||||
Or you can execute the command directly as the following.
|
||||
|
||||
3. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog.
|
||||
4. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected.
|
||||
5. Re-plug USB cord or click 'Start Application' button to restart your controller.
|
||||
$ dfu-programmer <controller> erase --force
|
||||
$ dfu-programmer <controller> flash <your_firmware.hex>
|
||||
$ dfu-programmer <controller> reset
|
||||
|
||||
`<controller>` part will be `atmega32u4` or `atmega32u2` in most cases. See manual of the command for the detail. On Linux and Mac OSX you will need proper permission to program a controller and you can use `sudo` command for this purpose probably. On Linux you also can configure `udev` rules to set permission.
|
||||
|
||||
|
||||
#### FLIP GUI tutorial
|
||||
1. On menu bar click **Device** -> **Select**, then choose your chip name. (In most cases **ATmega32U2** or **ATmega32U4**)
|
||||
2. On menu bar click **Settings** -> **Communication** -> **USB**, then click **Open** button on **USB Port Connection** dialog. At this point you'll have to plug into USB and start bootloader.
|
||||
|
||||
3. On menu bar click **File** -> **Load HEX File**, then select your firmware hex file on File Selector dialog.
|
||||
4. On **Operations Flow** panel click **Run** button to load the firmware binary to the chip. Note that you should keep **Erase**, **Blank Check**, **Program** and **Verify** check boxes selected.
|
||||
5. Re-plug USB cord or click **Start Application** button to restart your controller.
|
||||
Done.
|
||||
|
||||
See also these instructions if you need.
|
||||
See also these instructions if needed.
|
||||
|
||||
- <http://code.google.com/p/micropendous/wiki/LoadingFirmwareWithFLIP>
|
||||
- <http://www.atmel.com/Images/doc7769.pdf>
|
||||
|
||||
|
||||
### 3. Program with Teensy Loader
|
||||
If you have PJRC Teensy see instruction of `Teensy Loader`.
|
||||
##### Troubleshoot
|
||||
* **FLIP: AtLibUsbDfu.dll not found**
|
||||
Remove current driver and re-install one FLIP provides from DeviceManager of WIndows. See <http://imgur.com/a/bnwzy>
|
||||
|
||||
- <http://www.pjrc.com/teensy/loader.html>
|
||||
|
||||
Or use this command if you have command line version of Teensy Loader installed.
|
||||
### 3. Program with Other programmer
|
||||
If you are using PJRC Teensy consult with instruction of [Teensy Loader][teensy-loader]. Or run this target with `make` after you install command line version of it.
|
||||
|
||||
$ make -f Makefile.<variant> teensy
|
||||
|
||||
|
||||
### 4. Program with Other programmer
|
||||
You may want to use other programmer like `avrdude` with AVRISPmkII, Arduino or USBasp. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile.
|
||||
You may want to use other programmer like [`avrdude`][avrdude]. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile. See below.
|
||||
|
||||
$ make -f Makefile.<variant> program
|
||||
|
||||
|
||||
[atmelgcc]: http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx
|
||||
[cygwin]: https://www.cygwin.com/
|
||||
[mingw]: http://www.mingw.org/
|
||||
[mhv]: https://infernoembedded.com/products/avr-tools
|
||||
[winavr]: http://winavr.sourceforge.net/
|
||||
[crosspack]: http://www.obdev.at/products/crosspack/index.html
|
||||
[flip]: http://www.atmel.com/tools/FLIP.aspx
|
||||
[dfu-prog]: http://dfu-programmer.sourceforge.net/
|
||||
[teensy-loader]:http://www.pjrc.com/teensy/loader.html
|
||||
[avrdude]: http://savannah.nongnu.org/projects/avrdude/
|
||||
[git]: https://git-scm.com/
|
||||
|
||||
|
||||
|
||||
@ -122,6 +127,7 @@ Set your MCU and its clock in Hz.
|
||||
|
||||
# Boot Section Size in *bytes*
|
||||
# Teensy halfKay 512
|
||||
# Teensy++ halfKay 2048
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=4096
|
||||
@ -141,7 +147,7 @@ Optional. Note that ***comment out*** with `#` to disable them.
|
||||
#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
|
||||
|
||||
### 3. Programmer
|
||||
Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`. Not needed if you use `FLIP`, `dfu-programmer` or `Teensy Loader`.
|
||||
Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`.
|
||||
|
||||
# avrdude with AVRISPmkII
|
||||
PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex
|
||||
|
@ -368,17 +368,37 @@ Default Layer also has bitwise operations, they are executed when key is release
|
||||
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
|
||||
|
||||
#### 2.3.1 Macro Commands
|
||||
- **MACRO()**
|
||||
- **MACRO_NONE**
|
||||
|
||||
- **I()** change interval of stroke.
|
||||
- **D()** press key
|
||||
- **U()** release key
|
||||
- **T()** type key(press and release)
|
||||
- **W()** wait
|
||||
- **SM()** store modifier state
|
||||
- **RM()** restore modifier state
|
||||
- **CM()** clear modifier state
|
||||
- **END** end mark
|
||||
|
||||
#### 2.3.2 Examples
|
||||
***TBD***
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
switch (id) {
|
||||
case HELLO:
|
||||
return (record->event.pressed ?
|
||||
MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
|
||||
MACRO_NONE );
|
||||
case ALT_TAB:
|
||||
return (record->event.pressed ?
|
||||
MACRO( D(LALT), D(TAB), END ) :
|
||||
MACRO( U(TAB), END ));
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
***TODO: sample implementation***
|
||||
See `keyboard/hhkb/keymap.c` for sample.
|
||||
|
||||
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
Other Keyboard Firmware Projects
|
||||
================================
|
||||
## PJRC USB Keyboard/Mouse Example[USB][PJRC][Teensy][AVR]
|
||||
- <http://www.pjrc.com/teensy/usb_keyboard.html>
|
||||
- <http://www.pjrc.com/teensy/usb_mouse.html>
|
||||
|
||||
## kbupgrade[USB][V-USB][AVR]
|
||||
- <http://github.com/rhomann/kbupgrade>
|
||||
- <http://geekhack.org/showwiki.php?title=Island:8406>
|
||||
|
||||
## c64key[USB][V-USB][AVR]
|
||||
- <http://symlink.dk/projects/c64key/>
|
||||
|
||||
## rump[USB][V-USB][AVR]
|
||||
- <http://mg8.org/rump/>
|
||||
- <http://github.com/clee/rump>
|
||||
|
||||
## dulcimer[USB][V-USB][AVR]
|
||||
- <http://www.schatenseite.de/dulcimer.html>
|
||||
|
||||
## humblehacker-keyboard[USB][LUFA][AVR][Ergo]
|
||||
- <http://github.com/humblehacker>
|
||||
- <http://www.humblehacker.com/keyboard/>
|
||||
- <http://geekhack.org/showwiki.php?title=Island:6292>
|
||||
|
||||
## ps2avr[PS/2][AVR]
|
||||
- <http://sourceforge.net/projects/ps2avr/>
|
||||
|
||||
## ErgoDox[Ergo][Split][USB][AVR]
|
||||
- <http://geekhack.org/index.php?topic=22780.0>
|
||||
- <https://github.com/benblazak/ergodox-firmware>
|
||||
- <https://github.com/cub-uanic/tmk_keyboard>
|
||||
|
||||
## Suka's keyboard collection[Ergo][Split][3DPrinting][USB][AVR]
|
||||
- <http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html>
|
||||
- <https://github.com/frobiac/adnw>
|
||||
|
||||
## bpiphany's AVR-Keyboard[PJRC][AVR][USB]
|
||||
- <https://github.com/BathroomEpiphanies/AVR-Keyboard>
|
||||
- <http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions>
|
||||
- <http://deskthority.net/wiki/Phantom>
|
||||
|
||||
## USB-USB keyboard remapper[converter][USB-USB][AVR][Arduino]
|
||||
- <http://forum.colemak.com/viewtopic.php?pid=10837>
|
||||
- <https://github.com/darkytoothpaste/keymapper>
|
||||
|
||||
## USB-USB converter threads[converter][USB-USB]
|
||||
- <http://deskthority.net/workshop-f7/is-remapping-a-usb-keyboard-using-teensy-possible-t2841-30.html>
|
||||
- <http://geekhack.org/index.php?topic=19458.0>
|
||||
|
||||
## kbdbabel.org[converter][vintage][protocol][8051]
|
||||
Great resource of vintage keyboard protocol information and code
|
||||
|
||||
- <http://www.kbdbabel.org/>
|
||||
|
||||
## Haata's kiibohd Controller[converter][vintage][protocol][AVR][PJRC][Cortex]
|
||||
A lots of vintage keyboard protocol supports
|
||||
|
||||
- <http://gitorious.org/kiibohd-controller>
|
||||
|
||||
## Kinesis ergonomic keyboard firmware replacement[V-USB][LUFA][Ergo]
|
||||
- <https://github.com/chrisandreae/kinesis-firmware>
|
50
protocol/chibios/README.md
Normal file
50
protocol/chibios/README.md
Normal file
@ -0,0 +1,50 @@
|
||||
## TMK running on top of ChibiOS
|
||||
|
||||
### Notes
|
||||
|
||||
- To use, unpack or symlink [ChibiOS] {currently 3.0.2} to `tmk_core/tool/chibios/chibios`. For Kinetis support, you'll need a fork which implements the USB driver, e.g. [this one](https://github.com/flabbergast/ChibiOS/tree/kinetis).
|
||||
- For gcc options, inspect `tmk_core/tool/chibios/chibios.mk`. For instance, I enabled `-Wno-missing-field-initializers`, because TMK common bits generated a lot of warnings on that.
|
||||
Also pay attention to `-O0` (enabled for debugging); for deployment use `-O2`.
|
||||
- USB string descriptors are messy. I did not find a way to cleanly generate the right structures from actual strings, so the definitions in individual keyboards' `config.h` are ugly as heck.
|
||||
- There are some random constants left so far, e.g. 5ms sleep between calling `keyboard_task`, or 1.5sec wait for USB init, in `main.c`. There should be no such in `usb_main.c` (the main USB stack). Everything is based on timers/interrupts/kernel scheduling (well except `keyboard_task`), so no periodically called things (again, except `keyboard_task`, which is just how TMK is designed).
|
||||
- It is easy to add some code for testing (e.g. blink LED, do stuff on button press, etc...) - just create another thread in `main.c`, it will run independently of the keyboard business.
|
||||
- Jumping to (the built-in) bootloaders on STM32 works, but it is not entirely pleasant, since it is very much MCU dependent. So, one needs to dig out the right address to jump to, and either pass it to the compiler in the `Makefile`, or better, define it in `<your_kb>/bootloader_defs.h`. Also, a patch to upstream ChibiOS is needed (supplied), because it `ResetHandler` needs adjusting.
|
||||
- Sleep LED works, but at the moment only on/off, i.e. no breathing.
|
||||
|
||||
### Immediate todo
|
||||
|
||||
- host-wakeup packet sending during suspend
|
||||
- power saving for suspend?
|
||||
- PWM for sleep led
|
||||
|
||||
### Not tested, but possibly working
|
||||
|
||||
- backlight
|
||||
|
||||
### Missing / not working (TMK vs ChibiOS bits)
|
||||
|
||||
- eeprom / bootmagic for STM32 (will be chip dependent; eeprom needs to be emulated in flash, which means less writes; wear-levelling?) There is a semi-official ST "driver" for eeprom, with wear-levelling, but I think it consumes a lot of RAM (like 2 pages, i.e. 1kB or so).
|
||||
|
||||
### Tried with
|
||||
|
||||
- ChibiOS 3.0.1, 3.0.2 and ST F072RB DISCOVERY board.
|
||||
- Need to test on other STM32 chips (F3, F4) to make it as much chip-independent as possible.
|
||||
- ChibiOS with Kinetis patches and Teensy LC and 3.0.
|
||||
|
||||
## ChibiOS-supported MCUs (as of 3.0.2)
|
||||
|
||||
- Pretty much all STM32 chips.
|
||||
- There is some support for K20x and KL2x Freescale chips (i.e. Teensy 3.x/LC, mchck, FRDM-KL2{5,6}Z, FRDM-K20D50M), but again, no official USB stack yet. However the `kinetis` branch of [my ChibiOS fork](https://github.com/flabbergast/ChibiOS). With this fork, TMK work normally on all the ARM Teensies.
|
||||
- There is also support for AVR8, but the USB stack is not implemented for them yet, and also the kernel itself takes about 1k of RAM. I think people managed to get ChibiOS running on atmega32[8p/u4] though.
|
||||
- I've seen community support for Nordic NRF51822 (the chip in Adafruit's Bluefruit bluetooth-low-energy boards), but not sure about the extent.
|
||||
|
||||
## STM32-based keyboard design considerations
|
||||
|
||||
- STM32F0x2 chips can do crystal-less USB, but they still need a 3.3V voltage regulator.
|
||||
- The BOOT0 pin should be tied to GND.
|
||||
- For a hardware way of accessing the in-built DFU bootloader, in addition to the reset button, put another button between the BOOT0 pin and 3V3.
|
||||
- For breathing the caps lock LED during the suspended state ("sleep LED"), it is desirable to have that LED on a hardware PWM pin (there's usually plenty of those, look for TIMERs in the datasheet). However this is not strictly necessary, because instead of direct output of a timer to a pin (better of course), it is easy to define timer callbacks in ChibiOS that turn on/off an arbitrary pin.
|
||||
|
||||
|
||||
|
||||
[ChibiOS]: http://chibios.org
|
139
protocol/chibios/main.c
Normal file
139
protocol/chibios/main.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
|
||||
*
|
||||
* Based on the following work:
|
||||
* - Guillaume Duc's raw hid example (MIT License)
|
||||
* https://github.com/guiduc/usb-hid-chibios-example
|
||||
* - PJRC Teensy examples (MIT License)
|
||||
* https://www.pjrc.com/teensy/usb_keyboard.html
|
||||
* - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
|
||||
* https://github.com/tmk/tmk_keyboard/
|
||||
* - ChibiOS demo code (Apache 2.0 License)
|
||||
* http://www.chibios.org
|
||||
*
|
||||
* Since some GPL'd code is used, this work is licensed under
|
||||
* GPL v2 or later.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "usb_main.h"
|
||||
|
||||
/* TMK includes */
|
||||
#include "report.h"
|
||||
#include "host.h"
|
||||
#include "host_driver.h"
|
||||
#include "keyboard.h"
|
||||
#include "action.h"
|
||||
#include "action_util.h"
|
||||
#include "mousekey.h"
|
||||
#include "led.h"
|
||||
#include "sendchar.h"
|
||||
#include "debug.h"
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
#include "sleep_led.h"
|
||||
#endif
|
||||
#include "suspend.h"
|
||||
|
||||
|
||||
/* -------------------------
|
||||
* TMK host driver defs
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
/* declarations */
|
||||
uint8_t keyboard_leds(void);
|
||||
void send_keyboard(report_keyboard_t *report);
|
||||
void send_mouse(report_mouse_t *report);
|
||||
void send_system(uint16_t data);
|
||||
void send_consumer(uint16_t data);
|
||||
|
||||
/* host struct */
|
||||
host_driver_t chibios_driver = {
|
||||
keyboard_leds,
|
||||
send_keyboard,
|
||||
send_mouse,
|
||||
send_system,
|
||||
send_consumer
|
||||
};
|
||||
|
||||
|
||||
/* TESTING
|
||||
* Amber LED blinker thread, times are in milliseconds.
|
||||
*/
|
||||
/* set this variable to non-zero anywhere to blink once */
|
||||
// uint8_t blinkLed = 0;
|
||||
// static THD_WORKING_AREA(waBlinkerThread, 128);
|
||||
// static THD_FUNCTION(blinkerThread, arg) {
|
||||
// (void)arg;
|
||||
// chRegSetThreadName("blinkOrange");
|
||||
// while(true) {
|
||||
// if(blinkLed) {
|
||||
// blinkLed = 0;
|
||||
// palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
|
||||
// chThdSleepMilliseconds(100);
|
||||
// palClearPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
|
||||
// }
|
||||
// chThdSleepMilliseconds(100);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/* Main thread
|
||||
*/
|
||||
int main(void) {
|
||||
/* ChibiOS/RT init */
|
||||
halInit();
|
||||
chSysInit();
|
||||
|
||||
// TESTING
|
||||
// chThdCreateStatic(waBlinkerThread, sizeof(waBlinkerThread), NORMALPRIO, blinkerThread, NULL);
|
||||
|
||||
/* Init USB */
|
||||
init_usb_driver(&USB_DRIVER);
|
||||
|
||||
/* init printf */
|
||||
init_printf(NULL,sendchar_pf);
|
||||
|
||||
/* Wait until the USB is active */
|
||||
while(USB_DRIVER.state != USB_ACTIVE)
|
||||
chThdSleepMilliseconds(50);
|
||||
|
||||
print("USB configured.\n");
|
||||
|
||||
/* init TMK modules */
|
||||
keyboard_init();
|
||||
host_set_driver(&chibios_driver);
|
||||
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_init();
|
||||
#endif
|
||||
|
||||
print("Keyboard start.\n");
|
||||
|
||||
/* Main loop */
|
||||
while(true) {
|
||||
|
||||
if(USB_DRIVER.state == USB_SUSPENDED) {
|
||||
print("[s]");
|
||||
while(USB_DRIVER.state == USB_SUSPENDED) {
|
||||
/* Do this in the suspended state */
|
||||
suspend_power_down(); // on AVR this deep sleeps for 15ms
|
||||
/* Remote wakeup */
|
||||
if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) {
|
||||
send_remote_wakeup(&USB_DRIVER);
|
||||
}
|
||||
}
|
||||
/* Woken up */
|
||||
// variables has been already cleared by the wakeup hook
|
||||
send_keyboard_report();
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
mousekey_send();
|
||||
#endif /* MOUSEKEY_ENABLE */
|
||||
}
|
||||
|
||||
keyboard_task();
|
||||
}
|
||||
}
|
1372
protocol/chibios/usb_main.c
Normal file
1372
protocol/chibios/usb_main.c
Normal file
File diff suppressed because it is too large
Load Diff
143
protocol/chibios/usb_main.h
Normal file
143
protocol/chibios/usb_main.h
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
|
||||
*
|
||||
* Based on the following work:
|
||||
* - Guillaume Duc's raw hid example (MIT License)
|
||||
* https://github.com/guiduc/usb-hid-chibios-example
|
||||
* - PJRC Teensy examples (MIT License)
|
||||
* https://www.pjrc.com/teensy/usb_keyboard.html
|
||||
* - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
|
||||
* https://github.com/tmk/tmk_keyboard/
|
||||
* - ChibiOS demo code (Apache 2.0 License)
|
||||
* http://www.chibios.org
|
||||
*
|
||||
* Since some GPL'd code is used, this work is licensed under
|
||||
* GPL v2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _USB_MAIN_H_
|
||||
#define _USB_MAIN_H_
|
||||
|
||||
// TESTING
|
||||
// extern uint8_t blinkLed;
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/* -------------------------
|
||||
* General USB driver header
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
/* The USB driver to use */
|
||||
#define USB_DRIVER USBD1
|
||||
|
||||
/* Initialize the USB driver and bus */
|
||||
void init_usb_driver(USBDriver *usbp);
|
||||
|
||||
/* Send remote wakeup packet */
|
||||
void send_remote_wakeup(USBDriver *usbp);
|
||||
|
||||
/* ---------------
|
||||
* Keyboard header
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
/* main keyboard (6kro) */
|
||||
#define KBD_INTERFACE 0
|
||||
#define KBD_ENDPOINT 1
|
||||
#define KBD_EPSIZE 8
|
||||
#define KBD_REPORT_KEYS (KBD_EPSIZE - 2)
|
||||
|
||||
/* secondary keyboard */
|
||||
#ifdef NKRO_ENABLE
|
||||
#define NKRO_INTERFACE 4
|
||||
#define NKRO_ENDPOINT 5
|
||||
#define NKRO_EPSIZE 16
|
||||
#define NKRO_REPORT_KEYS (NKRO_EPSIZE - 1)
|
||||
#endif
|
||||
|
||||
/* this defines report_keyboard_t and computes REPORT_SIZE defines */
|
||||
// #include "report.h"
|
||||
|
||||
/* extern report_keyboard_t keyboard_report_sent; */
|
||||
|
||||
/* keyboard IN request callback handler */
|
||||
void kbd_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* start-of-frame handler */
|
||||
void kbd_sof_cb(USBDriver *usbp);
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* nkro IN callback hander */
|
||||
void nkro_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
#endif /* NKRO_ENABLE */
|
||||
|
||||
/* ------------
|
||||
* Mouse header
|
||||
* ------------
|
||||
*/
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
|
||||
#define MOUSE_INTERFACE 1
|
||||
#define MOUSE_ENDPOINT 2
|
||||
#define MOUSE_EPSIZE 8
|
||||
|
||||
/* mouse IN request callback handler */
|
||||
void mouse_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------
|
||||
* Extrakey header
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
|
||||
#define EXTRA_INTERFACE 3
|
||||
#define EXTRA_ENDPOINT 4
|
||||
#define EXTRA_EPSIZE 8
|
||||
|
||||
/* extrakey IN request callback handler */
|
||||
void extra_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* extra report structure */
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
uint16_t usage;
|
||||
} __attribute__ ((packed)) report_extra_t;
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
|
||||
/* --------------
|
||||
* Console header
|
||||
* --------------
|
||||
*/
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|
||||
#define CONSOLE_INTERFACE 2
|
||||
#define CONSOLE_ENDPOINT 3
|
||||
#define CONSOLE_EPSIZE 16
|
||||
|
||||
/* Number of IN reports that can be stored inside the output queue */
|
||||
#define CONSOLE_QUEUE_CAPACITY 2
|
||||
#define CONSOLE_QUEUE_BUFFER_SIZE (CONSOLE_QUEUE_CAPACITY * CONSOLE_EPSIZE)
|
||||
|
||||
/* Console flush time */
|
||||
#define CONSOLE_FLUSH_MS 50
|
||||
|
||||
/* Putchar over the USB console */
|
||||
int8_t sendchar(uint8_t c);
|
||||
|
||||
/* Flush output (send everything immediately) */
|
||||
void console_flush_output(void);
|
||||
|
||||
/* console IN request callback handler */
|
||||
void console_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
#endif /* CONSOLE_ENABLE */
|
||||
|
||||
void sendchar_pf(void *p, char c);
|
||||
|
||||
#endif /* _USB_MAIN_H_ */
|
@ -68,7 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#endif
|
||||
|
||||
/* debug for signal timing, see debug pin with oscilloscope */
|
||||
#define SERIAL_SOFT_DEBUG
|
||||
#ifdef SERIAL_SOFT_DEBUG
|
||||
#define SERIAL_SOFT_DEBUG_INIT() (DDRD |= 1<<7)
|
||||
#define SERIAL_SOFT_DEBUG_TGL() (PORTD ^= 1<<7)
|
||||
@ -176,7 +175,7 @@ void serial_send(uint8_t data)
|
||||
ISR(SERIAL_SOFT_RXD_VECT)
|
||||
{
|
||||
SERIAL_SOFT_DEBUG_TGL();
|
||||
SERIAL_SOFT_RXD_INT_ENTER()
|
||||
SERIAL_SOFT_RXD_INT_ENTER();
|
||||
|
||||
uint8_t data = 0;
|
||||
|
||||
|
@ -13,7 +13,7 @@ void KBDReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
|
||||
bool is_error = false;
|
||||
report_keyboard_t *report = (report_keyboard_t *)buf;
|
||||
|
||||
dprintf("KBDReport: %02X %02X", report->mods, report->reserved);
|
||||
dprintf("keyboard input: %02X %02X", report->mods, report->reserved);
|
||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
|
||||
if (IS_ERROR(report->keys[i])) {
|
||||
is_error = true;
|
||||
|
1
rules.mk
1
rules.mk
@ -425,7 +425,6 @@ ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
|
||||
else
|
||||
dfu-programmer $(MCU) erase
|
||||
endif
|
||||
dfu-programmer $(MCU) erase
|
||||
dfu-programmer $(MCU) flash $(TARGET).hex
|
||||
dfu-programmer $(MCU) reset
|
||||
|
||||
|
1
tool/chibios/.gitignore
vendored
Normal file
1
tool/chibios/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
chibios
|
116
tool/chibios/ch-bootloader-jump.patch
Normal file
116
tool/chibios/ch-bootloader-jump.patch
Normal file
@ -0,0 +1,116 @@
|
||||
diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
|
||||
index 51a79bb..42d07bd 100644
|
||||
--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
|
||||
+++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
|
||||
@@ -105,6 +105,13 @@
|
||||
#define CRT0_CALL_DESTRUCTORS TRUE
|
||||
#endif
|
||||
|
||||
+/**
|
||||
+ * @brief Magic number for jumping to bootloader.
|
||||
+ */
|
||||
+#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
|
||||
+#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
|
||||
+#endif
|
||||
+
|
||||
/*===========================================================================*/
|
||||
/* Code section. */
|
||||
/*===========================================================================*/
|
||||
@@ -124,6 +131,17 @@
|
||||
.thumb_func
|
||||
.global Reset_Handler
|
||||
Reset_Handler:
|
||||
+
|
||||
+#ifdef STM32_BOOTLOADER_ADDRESS
|
||||
+ /* jump to bootloader code */
|
||||
+ ldr r0, =__ram0_end__-4
|
||||
+ ldr r1, =MAGIC_BOOTLOADER_NUMBER
|
||||
+ ldr r2, [r0, #0]
|
||||
+ str r0, [r0, #0] /* erase stored magic */
|
||||
+ cmp r2, r1
|
||||
+ beq Bootloader_Jump
|
||||
+#endif /* STM32_BOOTLOADER_ADDRESS */
|
||||
+
|
||||
/* Interrupts are globally masked initially.*/
|
||||
cpsid i
|
||||
|
||||
@@ -242,6 +260,21 @@ endfiniloop:
|
||||
ldr r1, =__default_exit
|
||||
bx r1
|
||||
|
||||
+#ifdef STM32_BOOTLOADER_ADDRESS
|
||||
+/*
|
||||
+ * Jump-to-bootloader function.
|
||||
+ */
|
||||
+
|
||||
+ .align 2
|
||||
+ .thumb_func
|
||||
+Bootloader_Jump:
|
||||
+ ldr r0, =STM32_BOOTLOADER_ADDRESS
|
||||
+ ldr r1, [r0, #0]
|
||||
+ mov sp, r1
|
||||
+ ldr r0, [r0, #4]
|
||||
+ bx r0
|
||||
+#endif /* STM32_BOOTLOADER_ADDRESS */
|
||||
+
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
|
||||
index 4812a29..dca9f88 100644
|
||||
--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
|
||||
+++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
|
||||
@@ -140,6 +140,13 @@
|
||||
#define CRT0_CPACR_INIT 0x00F00000
|
||||
#endif
|
||||
|
||||
+/**
|
||||
+ * @brief Magic number for jumping to bootloader.
|
||||
+ */
|
||||
+#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
|
||||
+#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
|
||||
+#endif
|
||||
+
|
||||
/*===========================================================================*/
|
||||
/* Code section. */
|
||||
/*===========================================================================*/
|
||||
@@ -164,6 +171,17 @@
|
||||
.thumb_func
|
||||
.global Reset_Handler
|
||||
Reset_Handler:
|
||||
+
|
||||
+#ifdef STM32_BOOTLOADER_ADDRESS
|
||||
+ /* jump to bootloader code */
|
||||
+ ldr r0, =__ram0_end__-4
|
||||
+ ldr r1, =MAGIC_BOOTLOADER_NUMBER
|
||||
+ ldr r2, [r0, #0]
|
||||
+ str r0, [r0, #0] /* erase stored magic */
|
||||
+ cmp r2, r1
|
||||
+ beq Bootloader_Jump
|
||||
+#endif /* STM32_BOOTLOADER_ADDRESS */
|
||||
+
|
||||
/* Interrupts are globally masked initially.*/
|
||||
cpsid i
|
||||
|
||||
@@ -305,6 +323,21 @@ endfiniloop:
|
||||
/* Branching to the defined exit handler.*/
|
||||
b __default_exit
|
||||
|
||||
+#ifdef STM32_BOOTLOADER_ADDRESS
|
||||
+/*
|
||||
+ * Jump-to-bootloader function.
|
||||
+ */
|
||||
+
|
||||
+ .align 2
|
||||
+ .thumb_func
|
||||
+Bootloader_Jump:
|
||||
+ ldr r0, =STM32_BOOTLOADER_ADDRESS
|
||||
+ ldr r1, [r0, #0]
|
||||
+ mov sp, r1
|
||||
+ ldr r0, [r0, #4]
|
||||
+ bx r0
|
||||
+#endif /* STM32_BOOTLOADER_ADDRESS */
|
||||
+
|
||||
#endif /* !defined(__DOXYGEN__) */
|
||||
|
||||
/** @} */
|
231
tool/chibios/chibios.mk
Normal file
231
tool/chibios/chibios.mk
Normal file
@ -0,0 +1,231 @@
|
||||
##############################################################################
|
||||
# Build global options
|
||||
# NOTE: Can be overridden externally.
|
||||
#
|
||||
|
||||
# Compiler options here.
|
||||
ifeq ($(USE_OPT),)
|
||||
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -std=gnu99 -DPROTOCOL_CHIBIOS
|
||||
endif
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
ifeq ($(USE_COPT),)
|
||||
USE_COPT =
|
||||
endif
|
||||
|
||||
# include specific config.h?
|
||||
ifdef CONFIG_H
|
||||
USE_COPT += -include $(CONFIG_H)
|
||||
endif
|
||||
|
||||
# C++ specific options here (added to USE_OPT).
|
||||
ifeq ($(USE_CPPOPT),)
|
||||
USE_CPPOPT = -fno-rtti
|
||||
endif
|
||||
|
||||
# Enable this if you want the linker to remove unused code and data
|
||||
ifeq ($(USE_LINK_GC),)
|
||||
USE_LINK_GC = yes
|
||||
endif
|
||||
|
||||
# Linker extra options here.
|
||||
ifeq ($(USE_LDOPT),)
|
||||
USE_LDOPT =
|
||||
endif
|
||||
|
||||
# Enable this if you want link time optimizations (LTO)
|
||||
ifeq ($(USE_LTO),)
|
||||
USE_LTO = yes
|
||||
endif
|
||||
|
||||
# If enabled, this option allows to compile the application in THUMB mode.
|
||||
ifeq ($(USE_THUMB),)
|
||||
USE_THUMB = yes
|
||||
endif
|
||||
|
||||
# Enable this if you want to see the full log while compiling.
|
||||
ifeq ($(USE_VERBOSE_COMPILE),)
|
||||
USE_VERBOSE_COMPILE = no
|
||||
endif
|
||||
|
||||
# If enabled, this option makes the build process faster by not compiling
|
||||
# modules not used in the current configuration.
|
||||
ifeq ($(USE_SMART_BUILD),)
|
||||
USE_SMART_BUILD = yes
|
||||
endif
|
||||
|
||||
#
|
||||
# Build global options
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Architecture or project specific options
|
||||
#
|
||||
|
||||
# Stack size to be allocated to the Cortex-M process stack. This stack is
|
||||
# the stack used by the main() thread.
|
||||
ifeq ($(USE_PROCESS_STACKSIZE),)
|
||||
USE_PROCESS_STACKSIZE = 0x200
|
||||
endif
|
||||
|
||||
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
|
||||
# stack is used for processing interrupts and exceptions.
|
||||
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
|
||||
USE_EXCEPTIONS_STACKSIZE = 0x400
|
||||
endif
|
||||
|
||||
#
|
||||
# Architecture or project specific options
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Project, sources and paths
|
||||
#
|
||||
|
||||
# Imported source files and paths
|
||||
CHIBIOS = $(TMK_DIR)/tool/chibios/chibios
|
||||
# Startup files.
|
||||
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
|
||||
# HAL-OSAL files (optional).
|
||||
include $(CHIBIOS)/os/hal/hal.mk
|
||||
include $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/platform.mk
|
||||
ifneq ("$(wildcard $(TARGET_DIR)/boards/$(BOARD))","")
|
||||
include $(TARGET_DIR)/boards/$(BOARD)/board.mk
|
||||
else
|
||||
include $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
|
||||
endif
|
||||
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
|
||||
# RTOS files (optional).
|
||||
include $(CHIBIOS)/os/rt/rt.mk
|
||||
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
|
||||
# Other files (optional).
|
||||
|
||||
# Define linker script file here
|
||||
ifneq ("$(wildcard $(TARGET_DIR)/ld/$(MCU_LDSCRIPT).ld)","")
|
||||
LDSCRIPT = $(TARGET_DIR)/ld/$(MCU_LDSCRIPT).ld
|
||||
else
|
||||
LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
|
||||
endif
|
||||
|
||||
# C sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CSRC = $(STARTUPSRC) \
|
||||
$(KERNSRC) \
|
||||
$(PORTSRC) \
|
||||
$(OSALSRC) \
|
||||
$(HALSRC) \
|
||||
$(PLATFORMSRC) \
|
||||
$(BOARDSRC) \
|
||||
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
|
||||
$(TMK_DIR)/protocol/chibios/usb_main.c \
|
||||
$(TMK_DIR)/protocol/chibios/main.c \
|
||||
$(SRC)
|
||||
|
||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CPPSRC =
|
||||
|
||||
# C sources to be compiled in ARM mode regardless of the global setting.
|
||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||
# option that results in lower performance and larger code size.
|
||||
ACSRC =
|
||||
|
||||
# C++ sources to be compiled in ARM mode regardless of the global setting.
|
||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||
# option that results in lower performance and larger code size.
|
||||
ACPPSRC =
|
||||
|
||||
# C sources to be compiled in THUMB mode regardless of the global setting.
|
||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||
# option that results in lower performance and larger code size.
|
||||
TCSRC =
|
||||
|
||||
# C sources to be compiled in THUMB mode regardless of the global setting.
|
||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||
# option that results in lower performance and larger code size.
|
||||
TCPPSRC =
|
||||
|
||||
# List ASM source files here
|
||||
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
|
||||
|
||||
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
|
||||
$(CHIBIOS)/os/hal/lib/streams $(CHIBIOS)/os/various \
|
||||
$(TMK_DIR) $(COMMON_DIR) $(TMK_DIR)/protocol/chibios \
|
||||
$(TMK_DIR)/protocol $(TARGET_DIR)
|
||||
|
||||
#
|
||||
# Project, sources and paths
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Compiler settings
|
||||
#
|
||||
|
||||
#TRGT = arm-elf-
|
||||
TRGT = arm-none-eabi-
|
||||
CC = $(TRGT)gcc
|
||||
CPPC = $(TRGT)g++
|
||||
# Enable loading with g++ only if you need C++ runtime support.
|
||||
# NOTE: You can use C++ even without C++ support if you are careful. C++
|
||||
# runtime support makes code size explode.
|
||||
LD = $(TRGT)gcc
|
||||
#LD = $(TRGT)g++
|
||||
CP = $(TRGT)objcopy
|
||||
AS = $(TRGT)gcc -x assembler-with-cpp
|
||||
AR = $(TRGT)ar
|
||||
OD = $(TRGT)objdump
|
||||
SZ = $(TRGT)size
|
||||
HEX = $(CP) -O ihex
|
||||
BIN = $(CP) -O binary
|
||||
|
||||
# ARM-specific options here
|
||||
AOPT =
|
||||
|
||||
# THUMB-specific options here
|
||||
TOPT = -mthumb -DTHUMB
|
||||
|
||||
# Define C warning options here
|
||||
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes -Wno-missing-field-initializers
|
||||
|
||||
# Define C++ warning options here
|
||||
CPPWARN = -Wall -Wextra -Wundef
|
||||
|
||||
#
|
||||
# Compiler settings
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Start of user section
|
||||
#
|
||||
|
||||
# List all user C define here, like -D_DEBUG=1
|
||||
## Select which interfaces to include here!
|
||||
UDEFS = $(OPT_DEFS)
|
||||
|
||||
# Define ASM defines here
|
||||
UADEFS = $(OPT_DEFS)
|
||||
# bootloader definitions may be used in the startup .s file
|
||||
ifneq ("$(wildcard $(TARGET_DIR)/bootloader_defs.h)","")
|
||||
UADEFS += -include $(TARGET_DIR)/bootloader_defs.h
|
||||
UDEFS += -include $(TARGET_DIR)/bootloader_defs.h
|
||||
else ifneq ("$(wildcard $(TARGET_DIR)/boards/$(BOARD)/bootloader_defs.h)","")
|
||||
UADEFS += -include $(TARGET_DIR)/boards/$(BOARD)/bootloader_defs.h
|
||||
UDEFS += -include $(TARGET_DIR)/boards/$(BOARD)/bootloader_defs.h
|
||||
endif
|
||||
|
||||
# List all user directories here
|
||||
UINCDIR =
|
||||
|
||||
# List the user directory to look for the libraries here
|
||||
ULIBDIR =
|
||||
|
||||
# List all user libraries here
|
||||
ULIBS =
|
||||
|
||||
#
|
||||
# End of user defines
|
||||
##############################################################################
|
||||
|
||||
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
|
||||
include $(RULESPATH)/rules.mk
|
85
tool/chibios/common.mk
Normal file
85
tool/chibios/common.mk
Normal file
@ -0,0 +1,85 @@
|
||||
COMMON_DIR = $(TMK_DIR)/common
|
||||
SRC += $(COMMON_DIR)/host.c \
|
||||
$(COMMON_DIR)/keyboard.c \
|
||||
$(COMMON_DIR)/action.c \
|
||||
$(COMMON_DIR)/action_tapping.c \
|
||||
$(COMMON_DIR)/action_macro.c \
|
||||
$(COMMON_DIR)/action_layer.c \
|
||||
$(COMMON_DIR)/action_util.c \
|
||||
$(COMMON_DIR)/keymap.c \
|
||||
$(COMMON_DIR)/print.c \
|
||||
$(COMMON_DIR)/debug.c \
|
||||
$(COMMON_DIR)/util.c \
|
||||
$(COMMON_DIR)/chibios/suspend.c \
|
||||
$(COMMON_DIR)/chibios/printf.c \
|
||||
$(COMMON_DIR)/chibios/timer.c \
|
||||
$(COMMON_DIR)/chibios/bootloader.c
|
||||
|
||||
|
||||
# Option modules
|
||||
ifdef BOOTMAGIC_ENABLE
|
||||
SRC += $(COMMON_DIR)/bootmagic.c
|
||||
SRC += $(COMMON_DIR)/chibios/eeconfig.c
|
||||
OPT_DEFS += -DBOOTMAGIC_ENABLE
|
||||
endif
|
||||
|
||||
ifdef MOUSEKEY_ENABLE
|
||||
SRC += $(COMMON_DIR)/mousekey.c
|
||||
OPT_DEFS += -DMOUSEKEY_ENABLE
|
||||
OPT_DEFS += -DMOUSE_ENABLE
|
||||
endif
|
||||
|
||||
ifdef EXTRAKEY_ENABLE
|
||||
OPT_DEFS += -DEXTRAKEY_ENABLE
|
||||
endif
|
||||
|
||||
ifdef CONSOLE_ENABLE
|
||||
OPT_DEFS += -DCONSOLE_ENABLE
|
||||
else
|
||||
OPT_DEFS += -DNO_PRINT
|
||||
OPT_DEFS += -DNO_DEBUG
|
||||
endif
|
||||
|
||||
ifdef COMMAND_ENABLE
|
||||
SRC += $(COMMON_DIR)/command.c
|
||||
OPT_DEFS += -DCOMMAND_ENABLE
|
||||
endif
|
||||
|
||||
ifdef NKRO_ENABLE
|
||||
OPT_DEFS += -DNKRO_ENABLE
|
||||
endif
|
||||
|
||||
ifdef USB_6KRO_ENABLE
|
||||
OPT_DEFS += -DUSB_6KRO_ENABLE
|
||||
endif
|
||||
|
||||
ifdef SLEEP_LED_ENABLE
|
||||
SRC += $(COMMON_DIR)/chibios/sleep_led.c
|
||||
OPT_DEFS += -DSLEEP_LED_ENABLE
|
||||
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
|
||||
endif
|
||||
|
||||
ifdef BACKLIGHT_ENABLE
|
||||
SRC += $(COMMON_DIR)/backlight.c
|
||||
OPT_DEFS += -DBACKLIGHT_ENABLE
|
||||
endif
|
||||
|
||||
ifdef KEYMAP_SECTION_ENABLE
|
||||
OPT_DEFS += -DKEYMAP_SECTION_ENABLE
|
||||
|
||||
ifeq ($(strip $(MCU)),atmega32u2)
|
||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
|
||||
else ifeq ($(strip $(MCU)),atmega32u4)
|
||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
|
||||
else
|
||||
EXTRALDFLAGS = $(error no ldscript for keymap section)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Version string
|
||||
OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
|
||||
|
||||
# Bootloader address
|
||||
ifdef BOOTLOADER_ADDRESS
|
||||
OPT_DEFS += -DBOOTLOADER_ADDRESS=$(BOOTLOADER_ADDRESS)
|
||||
endif
|
@ -63,7 +63,7 @@ endif
|
||||
|
||||
ifdef SLEEP_LED_ENABLE
|
||||
$(error Not Supported)
|
||||
SRC += common/sleep_led.c
|
||||
SRC += common/mbed/sleep_led.c
|
||||
OPT_DEFS += -DSLEEP_LED_ENABLE
|
||||
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
|
||||
endif
|
||||
|
Loading…
Reference in New Issue
Block a user