Squashed 'tmk_core/' content from commit 05caacc
git-subtree-dir: tmk_core git-subtree-split: 05caaccec92694bb24c8c3c3a9940b96efd4605c
This commit is contained in:
		
						commit
						a074364c37
					
				
					 533 changed files with 102049 additions and 0 deletions
				
			
		
							
								
								
									
										565
									
								
								common/action.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										565
									
								
								common/action.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,565 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "mousekey.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "backlight.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "action_tapping.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void action_exec(keyevent_t event)
 | 
			
		||||
{
 | 
			
		||||
    if (!IS_NOEVENT(event)) {
 | 
			
		||||
        dprint("\n---- action_exec: start -----\n");
 | 
			
		||||
        dprint("EVENT: "); debug_event(event); dprintln();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    keyrecord_t record = { .event = event };
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
    action_tapping_process(record);
 | 
			
		||||
#else
 | 
			
		||||
    process_action(&record);
 | 
			
		||||
    if (!IS_NOEVENT(record.event)) {
 | 
			
		||||
        dprint("processed: "); debug_record(record); dprintln();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_action(keyrecord_t *record)
 | 
			
		||||
{
 | 
			
		||||
    keyevent_t event = record->event;
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
    uint8_t tap_count = record->tap.count;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (IS_NOEVENT(event)) { return; }
 | 
			
		||||
 | 
			
		||||
    action_t action = layer_switch_get_action(event.key);
 | 
			
		||||
    dprint("ACTION: "); debug_action(action);
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
    dprint(" layer_state: "); layer_debug();
 | 
			
		||||
    dprint(" default_layer_state: "); default_layer_debug();
 | 
			
		||||
#endif
 | 
			
		||||
    dprintln();
 | 
			
		||||
 | 
			
		||||
    switch (action.kind.id) {
 | 
			
		||||
        /* Key and Mods */
 | 
			
		||||
        case ACT_LMODS:
 | 
			
		||||
        case ACT_RMODS:
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
 | 
			
		||||
                                                                action.key.mods<<4;
 | 
			
		||||
                if (event.pressed) {
 | 
			
		||||
                    if (mods) {
 | 
			
		||||
                        add_weak_mods(mods);
 | 
			
		||||
                        send_keyboard_report();
 | 
			
		||||
                    }
 | 
			
		||||
                    register_code(action.key.code);
 | 
			
		||||
                } else {
 | 
			
		||||
                    unregister_code(action.key.code);
 | 
			
		||||
                    if (mods) {
 | 
			
		||||
                        del_weak_mods(mods);
 | 
			
		||||
                        send_keyboard_report();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
        case ACT_LMODS_TAP:
 | 
			
		||||
        case ACT_RMODS_TAP:
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
 | 
			
		||||
                                                                    action.key.mods<<4;
 | 
			
		||||
                switch (action.layer_tap.code) {
 | 
			
		||||
    #ifndef NO_ACTION_ONESHOT
 | 
			
		||||
                    case MODS_ONESHOT:
 | 
			
		||||
                        // Oneshot modifier
 | 
			
		||||
                        if (event.pressed) {
 | 
			
		||||
                            if (tap_count == 0) {
 | 
			
		||||
                                register_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (tap_count == 1) {
 | 
			
		||||
                                dprint("MODS_TAP: Oneshot: start\n");
 | 
			
		||||
                                set_oneshot_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                register_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            if (tap_count == 0) {
 | 
			
		||||
                                clear_oneshot_mods();
 | 
			
		||||
                                unregister_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (tap_count == 1) {
 | 
			
		||||
                                // Retain Oneshot mods
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                clear_oneshot_mods();
 | 
			
		||||
                                unregister_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
    #endif
 | 
			
		||||
                    case MODS_TAP_TOGGLE:
 | 
			
		||||
                        if (event.pressed) {
 | 
			
		||||
                            if (tap_count <= TAPPING_TOGGLE) {
 | 
			
		||||
                                register_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            if (tap_count < TAPPING_TOGGLE) {
 | 
			
		||||
                                unregister_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        if (event.pressed) {
 | 
			
		||||
                            if (tap_count > 0) {
 | 
			
		||||
                                if (record->tap.interrupted) {
 | 
			
		||||
                                    dprint("MODS_TAP: Tap: Cancel: add_mods\n");
 | 
			
		||||
                                    // ad hoc: set 0 to cancel tap
 | 
			
		||||
                                    record->tap.count = 0;
 | 
			
		||||
                                    register_mods(mods);
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    dprint("MODS_TAP: Tap: register_code\n");
 | 
			
		||||
                                    register_code(action.key.code);
 | 
			
		||||
                                }
 | 
			
		||||
                            } else {
 | 
			
		||||
                                dprint("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                                register_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            if (tap_count > 0) {
 | 
			
		||||
                                dprint("MODS_TAP: Tap: unregister_code\n");
 | 
			
		||||
                                unregister_code(action.key.code);
 | 
			
		||||
                            } else {
 | 
			
		||||
                                dprint("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                                unregister_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
        /* other HID usage */
 | 
			
		||||
        case ACT_USAGE:
 | 
			
		||||
            switch (action.usage.page) {
 | 
			
		||||
                case PAGE_SYSTEM:
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        host_system_send(action.usage.code);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        host_system_send(0);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case PAGE_CONSUMER:
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        host_consumer_send(action.usage.code);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        host_consumer_send(0);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
        /* Mouse key */
 | 
			
		||||
        case ACT_MOUSEKEY:
 | 
			
		||||
            if (event.pressed) {
 | 
			
		||||
                mousekey_on(action.key.code);
 | 
			
		||||
                mousekey_send();
 | 
			
		||||
            } else {
 | 
			
		||||
                mousekey_off(action.key.code);
 | 
			
		||||
                mousekey_send();
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
        case ACT_LAYER:
 | 
			
		||||
            if (action.layer_bitop.on == 0) {
 | 
			
		||||
                /* Default Layer Bitwise Operation */
 | 
			
		||||
                if (!event.pressed) {
 | 
			
		||||
                    uint8_t shift = action.layer_bitop.part*4;
 | 
			
		||||
                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
 | 
			
		||||
                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
 | 
			
		||||
                    switch (action.layer_bitop.op) {
 | 
			
		||||
                        case OP_BIT_AND: default_layer_and(bits | mask); break;
 | 
			
		||||
                        case OP_BIT_OR:  default_layer_or(bits | mask);  break;
 | 
			
		||||
                        case OP_BIT_XOR: default_layer_xor(bits | mask); break;
 | 
			
		||||
                        case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Layer Bitwise Operation */
 | 
			
		||||
                if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
 | 
			
		||||
                                    (action.layer_bitop.on & ON_RELEASE)) {
 | 
			
		||||
                    uint8_t shift = action.layer_bitop.part*4;
 | 
			
		||||
                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
 | 
			
		||||
                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
 | 
			
		||||
                    switch (action.layer_bitop.op) {
 | 
			
		||||
                        case OP_BIT_AND: layer_and(bits | mask); break;
 | 
			
		||||
                        case OP_BIT_OR:  layer_or(bits | mask);  break;
 | 
			
		||||
                        case OP_BIT_XOR: layer_xor(bits | mask); break;
 | 
			
		||||
                        case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    #ifndef NO_ACTION_TAPPING
 | 
			
		||||
        case ACT_LAYER_TAP:
 | 
			
		||||
        case ACT_LAYER_TAP_EXT:
 | 
			
		||||
            switch (action.layer_tap.code) {
 | 
			
		||||
                case 0xe0 ... 0xef:
 | 
			
		||||
                    /* layer On/Off with modifiers(left only) */
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        layer_on(action.layer_tap.val);
 | 
			
		||||
                        register_mods(action.layer_tap.code & 0x0f);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        layer_off(action.layer_tap.val);
 | 
			
		||||
                        unregister_mods(action.layer_tap.code & 0x0f);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case OP_TAP_TOGGLE:
 | 
			
		||||
                    /* tap toggle */
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        if (tap_count < TAPPING_TOGGLE) {
 | 
			
		||||
                            layer_invert(action.layer_tap.val);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (tap_count <= TAPPING_TOGGLE) {
 | 
			
		||||
                            layer_invert(action.layer_tap.val);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case OP_ON_OFF:
 | 
			
		||||
                    event.pressed ? layer_on(action.layer_tap.val) :
 | 
			
		||||
                                    layer_off(action.layer_tap.val);
 | 
			
		||||
                    break;
 | 
			
		||||
                case OP_OFF_ON:
 | 
			
		||||
                    event.pressed ? layer_off(action.layer_tap.val) :
 | 
			
		||||
                                    layer_on(action.layer_tap.val);
 | 
			
		||||
                    break;
 | 
			
		||||
                case OP_SET_CLEAR:
 | 
			
		||||
                    event.pressed ? layer_move(action.layer_tap.val) :
 | 
			
		||||
                                    layer_clear();
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    /* tap key */
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        if (tap_count > 0) {
 | 
			
		||||
                            dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
 | 
			
		||||
                            register_code(action.layer_tap.code);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
 | 
			
		||||
                            layer_on(action.layer_tap.val);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (tap_count > 0) {
 | 
			
		||||
                            dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
 | 
			
		||||
                            unregister_code(action.layer_tap.code);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
 | 
			
		||||
                            layer_off(action.layer_tap.val);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    #endif
 | 
			
		||||
#endif
 | 
			
		||||
        /* Extentions */
 | 
			
		||||
#ifndef NO_ACTION_MACRO
 | 
			
		||||
        case ACT_MACRO:
 | 
			
		||||
            action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
        case ACT_BACKLIGHT:
 | 
			
		||||
            if (!event.pressed) {
 | 
			
		||||
                switch (action.backlight.opt) {
 | 
			
		||||
                    case BACKLIGHT_INCREASE:
 | 
			
		||||
                        backlight_increase();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case BACKLIGHT_DECREASE:
 | 
			
		||||
                        backlight_decrease();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case BACKLIGHT_TOGGLE:
 | 
			
		||||
                        backlight_toggle();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case BACKLIGHT_STEP:
 | 
			
		||||
                        backlight_step();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case BACKLIGHT_LEVEL:
 | 
			
		||||
                        backlight_level(action.backlight.level);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        case ACT_COMMAND:
 | 
			
		||||
            break;
 | 
			
		||||
#ifndef NO_ACTION_FUNCTION
 | 
			
		||||
        case ACT_FUNCTION:
 | 
			
		||||
            action_function(record, action.func.id, action.func.opt);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Utilities for actions.
 | 
			
		||||
 */
 | 
			
		||||
void register_code(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if (code == KC_NO) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef LOCKING_SUPPORT_ENABLE
 | 
			
		||||
    else if (KC_LOCKING_CAPS == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        // Resync: ignore if caps lock already is on
 | 
			
		||||
        if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_CAPSLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_CAPSLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (KC_LOCKING_NUM == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_NUMLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_NUMLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (KC_LOCKING_SCROLL == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_SCROLLLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_SCROLLLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    else if IS_KEY(code) {
 | 
			
		||||
        // TODO: should push command_proc out of this block?
 | 
			
		||||
        if (command_proc(code)) return;
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
/* TODO: remove
 | 
			
		||||
        if (oneshot_state.mods && !oneshot_state.disabled) {
 | 
			
		||||
            uint8_t tmp_mods = get_mods();
 | 
			
		||||
            add_mods(oneshot_state.mods);
 | 
			
		||||
 | 
			
		||||
            add_key(code);
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
 | 
			
		||||
            set_mods(tmp_mods);
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
            oneshot_cancel();
 | 
			
		||||
        } else 
 | 
			
		||||
*/
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
            add_key(code);
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOD(code) {
 | 
			
		||||
        add_mods(MOD_BIT(code));
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_SYSTEM(code) {
 | 
			
		||||
        host_system_send(KEYCODE2SYSTEM(code));
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_CONSUMER(code) {
 | 
			
		||||
        host_consumer_send(KEYCODE2CONSUMER(code));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void unregister_code(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if (code == KC_NO) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef LOCKING_SUPPORT_ENABLE
 | 
			
		||||
    else if (KC_LOCKING_CAPS == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        // Resync: ignore if caps lock already is off
 | 
			
		||||
        if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_CAPSLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_CAPSLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (KC_LOCKING_NUM == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_NUMLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_NUMLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (KC_LOCKING_SCROLL == code) {
 | 
			
		||||
#ifdef LOCKING_RESYNC_ENABLE
 | 
			
		||||
        if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
 | 
			
		||||
#endif
 | 
			
		||||
        add_key(KC_SCROLLLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
        del_key(KC_SCROLLLOCK);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    else if IS_KEY(code) {
 | 
			
		||||
        del_key(code);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOD(code) {
 | 
			
		||||
        del_mods(MOD_BIT(code));
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_SYSTEM(code) {
 | 
			
		||||
        host_system_send(0);
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_CONSUMER(code) {
 | 
			
		||||
        host_consumer_send(0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_mods(uint8_t mods)
 | 
			
		||||
{
 | 
			
		||||
    if (mods) {
 | 
			
		||||
        add_mods(mods);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void unregister_mods(uint8_t mods)
 | 
			
		||||
{
 | 
			
		||||
    if (mods) {
 | 
			
		||||
        del_mods(mods);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_keyboard(void)
 | 
			
		||||
{
 | 
			
		||||
    clear_mods();
 | 
			
		||||
    clear_keyboard_but_mods();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_keyboard_but_mods(void)
 | 
			
		||||
{
 | 
			
		||||
    clear_weak_mods();
 | 
			
		||||
    clear_keys();
 | 
			
		||||
    send_keyboard_report();
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    mousekey_clear();
 | 
			
		||||
    mousekey_send();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
    host_system_send(0);
 | 
			
		||||
    host_consumer_send(0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool is_tap_key(keypos_t key)
 | 
			
		||||
{
 | 
			
		||||
    action_t action = layer_switch_get_action(key);
 | 
			
		||||
 | 
			
		||||
    switch (action.kind.id) {
 | 
			
		||||
        case ACT_LMODS_TAP:
 | 
			
		||||
        case ACT_RMODS_TAP:
 | 
			
		||||
        case ACT_LAYER_TAP:
 | 
			
		||||
        case ACT_LAYER_TAP_EXT:
 | 
			
		||||
            return true;
 | 
			
		||||
        case ACT_MACRO:
 | 
			
		||||
        case ACT_FUNCTION:
 | 
			
		||||
            if (action.func.opt & FUNC_TAP) { return true; }
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * debug print
 | 
			
		||||
 */
 | 
			
		||||
void debug_event(keyevent_t event)
 | 
			
		||||
{
 | 
			
		||||
    dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void debug_record(keyrecord_t record)
 | 
			
		||||
{
 | 
			
		||||
    debug_event(record.event);
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
    dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void debug_action(action_t action)
 | 
			
		||||
{
 | 
			
		||||
    switch (action.kind.id) {
 | 
			
		||||
        case ACT_LMODS:             dprint("ACT_LMODS");             break;
 | 
			
		||||
        case ACT_RMODS:             dprint("ACT_RMODS");             break;
 | 
			
		||||
        case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
 | 
			
		||||
        case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
 | 
			
		||||
        case ACT_USAGE:             dprint("ACT_USAGE");             break;
 | 
			
		||||
        case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
 | 
			
		||||
        case ACT_LAYER:             dprint("ACT_LAYER");             break;
 | 
			
		||||
        case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
 | 
			
		||||
        case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
 | 
			
		||||
        case ACT_MACRO:             dprint("ACT_MACRO");             break;
 | 
			
		||||
        case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
 | 
			
		||||
        case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
 | 
			
		||||
        default:                    dprint("UNKNOWN");               break;
 | 
			
		||||
    }
 | 
			
		||||
    dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								common/action.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								common/action.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_H
 | 
			
		||||
#define ACTION_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "action_code.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* tapping count and state */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool    interrupted :1;
 | 
			
		||||
    bool    reserved2   :1;
 | 
			
		||||
    bool    reserved1   :1;
 | 
			
		||||
    bool    reserved0   :1;
 | 
			
		||||
    uint8_t count       :4;
 | 
			
		||||
} tap_t;
 | 
			
		||||
 | 
			
		||||
/* Key event container for recording */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyevent_t  event;
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
    tap_t tap;
 | 
			
		||||
#endif
 | 
			
		||||
} keyrecord_t;
 | 
			
		||||
 | 
			
		||||
/* Execute action per keyevent */
 | 
			
		||||
void action_exec(keyevent_t event);
 | 
			
		||||
 | 
			
		||||
/* action for key */
 | 
			
		||||
action_t action_for_key(uint8_t layer, keypos_t key);
 | 
			
		||||
 | 
			
		||||
/* macro */
 | 
			
		||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
 | 
			
		||||
 | 
			
		||||
/* user defined special function */
 | 
			
		||||
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
 | 
			
		||||
 | 
			
		||||
/* Utilities for actions.  */
 | 
			
		||||
void process_action(keyrecord_t *record);
 | 
			
		||||
void register_code(uint8_t code);
 | 
			
		||||
void unregister_code(uint8_t code);
 | 
			
		||||
void register_mods(uint8_t mods);
 | 
			
		||||
void unregister_mods(uint8_t mods);
 | 
			
		||||
//void set_mods(uint8_t mods);
 | 
			
		||||
void clear_keyboard(void);
 | 
			
		||||
void clear_keyboard_but_mods(void);
 | 
			
		||||
void layer_switch(uint8_t new_layer);
 | 
			
		||||
bool is_tap_key(keypos_t key);
 | 
			
		||||
 | 
			
		||||
/* debug */
 | 
			
		||||
void debug_event(keyevent_t event);
 | 
			
		||||
void debug_record(keyrecord_t record);
 | 
			
		||||
void debug_action(action_t action);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  /* ACTION_H */
 | 
			
		||||
							
								
								
									
										315
									
								
								common/action_code.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								common/action_code.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,315 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_CODE_H
 | 
			
		||||
#define ACTION_CODE_H
 | 
			
		||||
 | 
			
		||||
/* Action codes
 | 
			
		||||
 * ============
 | 
			
		||||
 * 16bit code: action_kind(4bit) + action_parameter(12bit)
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Key Actions(00xx)
 | 
			
		||||
 * -----------------
 | 
			
		||||
 * ACT_MODS(000r):
 | 
			
		||||
 * 000r|0000|0000 0000    No action code
 | 
			
		||||
 * 000r|0000|0000 0001    Transparent code
 | 
			
		||||
 * 000r|0000| keycode     Key
 | 
			
		||||
 * 000r|mods|0000 0000    Modifiers
 | 
			
		||||
 * 000r|mods| keycode     Modifiers+Key(Modified key)
 | 
			
		||||
 *   r: Left/Right flag(Left:0, Right:1)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_MODS_TAP(001r):
 | 
			
		||||
 * 001r|mods|0000 0000    Modifiers with OneShot
 | 
			
		||||
 * 001r|mods|0000 0001    Modifiers with tap toggle
 | 
			
		||||
 * 001r|mods|0000 00xx    (reserved)
 | 
			
		||||
 * 001r|mods| keycode     Modifiers with Tap Key(Dual role)
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Other Keys(01xx)
 | 
			
		||||
 * ----------------
 | 
			
		||||
 * ACT_USAGE(0100): TODO: Not needed?
 | 
			
		||||
 * 0100|00| usage(10)     System control(0x80) - General Desktop page(0x01)
 | 
			
		||||
 * 0100|01| usage(10)     Consumer control(0x01) - Consumer page(0x0C)
 | 
			
		||||
 * 0100|10| usage(10)     (reserved)
 | 
			
		||||
 * 0100|11| usage(10)     (reserved)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_MOUSEKEY(0110): TODO: Not needed?
 | 
			
		||||
 * 0101|xxxx| keycode     Mouse key
 | 
			
		||||
 *
 | 
			
		||||
 * 011x|xxxx xxxx xxxx    (reseved)
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Layer Actions(10xx)
 | 
			
		||||
 * -------------------
 | 
			
		||||
 * ACT_LAYER(1000):
 | 
			
		||||
 * 1000|oo00|pppE BBBB   Default Layer Bitwise operation
 | 
			
		||||
 *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
 | 
			
		||||
 *   ppp:   4-bit chunk part(0-7)
 | 
			
		||||
 *   EBBBB: bits and extra bit
 | 
			
		||||
 * 1000|ooee|pppE BBBB   Layer Bitwise Operation
 | 
			
		||||
 *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
 | 
			
		||||
 *   ppp:   4-bit chunk part(0-7)
 | 
			
		||||
 *   EBBBB: bits and extra bit
 | 
			
		||||
 *   ee:    on event(01:press, 10:release, 11:both)
 | 
			
		||||
 *
 | 
			
		||||
 * 1001|xxxx|xxxx xxxx   (reserved)
 | 
			
		||||
 * 1001|oopp|BBBB BBBB   8-bit Bitwise Operation???
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_LAYER_TAP(101x):
 | 
			
		||||
 * 101E|LLLL| keycode    On/Off with tap key
 | 
			
		||||
 * 101E|LLLL|1110 mods   On/Off with modifiers(0xE0-EF)
 | 
			
		||||
 * 101E|LLLL|1111 0000   Invert with tap toggle(0xF0)
 | 
			
		||||
 * 101E|LLLL|1111 0001   On/Off
 | 
			
		||||
 * 101E|LLLL|1111 0010   Off/On
 | 
			
		||||
 * 101E|LLLL|1111 0011   Set/Clear
 | 
			
		||||
 * 101E|LLLL|1111 xxxx   Reserved(0xF4-FF)
 | 
			
		||||
 *   ELLLL: layer 0-31(E: extra bit for layer 16-31)
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Extensions(11xx)
 | 
			
		||||
 * ----------------
 | 
			
		||||
 * ACT_MACRO(1100):
 | 
			
		||||
 * 1100|opt | id(8)      Macro play?
 | 
			
		||||
 * 1100|1111| id(8)      Macro record?
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_BACKLIGHT(1101):
 | 
			
		||||
 * 1101|opt |level(8)    Backlight commands
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_COMMAND(1110):
 | 
			
		||||
 * 1110|opt | id(8)      Built-in Command exec
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_FUNCTION(1111):
 | 
			
		||||
 * 1111| address(12)     Function?
 | 
			
		||||
 * 1111|opt | id(8)      Function?
 | 
			
		||||
 */
 | 
			
		||||
enum action_kind_id {
 | 
			
		||||
    /* Key Actions */
 | 
			
		||||
    ACT_MODS            = 0b0000,
 | 
			
		||||
    ACT_LMODS           = 0b0000,
 | 
			
		||||
    ACT_RMODS           = 0b0001,
 | 
			
		||||
    ACT_MODS_TAP        = 0b0010,
 | 
			
		||||
    ACT_LMODS_TAP       = 0b0010,
 | 
			
		||||
    ACT_RMODS_TAP       = 0b0011,
 | 
			
		||||
    /* Other Keys */
 | 
			
		||||
    ACT_USAGE           = 0b0100,
 | 
			
		||||
    ACT_MOUSEKEY        = 0b0101,
 | 
			
		||||
    /* Layer Actions */
 | 
			
		||||
    ACT_LAYER           = 0b1000,
 | 
			
		||||
    ACT_LAYER_TAP       = 0b1010, /* Layer  0-15 */
 | 
			
		||||
    ACT_LAYER_TAP_EXT   = 0b1011, /* Layer 16-31 */
 | 
			
		||||
    /* Extensions */
 | 
			
		||||
    ACT_MACRO           = 0b1100,
 | 
			
		||||
    ACT_BACKLIGHT       = 0b1101,
 | 
			
		||||
    ACT_COMMAND         = 0b1110,
 | 
			
		||||
    ACT_FUNCTION        = 0b1111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Action Code Struct
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE:
 | 
			
		||||
 * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
 | 
			
		||||
 * AVR looks like a little endian in avr-gcc.
 | 
			
		||||
 * Not portable across compiler/endianness?
 | 
			
		||||
 *
 | 
			
		||||
 * Byte order and bit order of 0x1234:
 | 
			
		||||
 *   Big endian:                Little endian:
 | 
			
		||||
 *   --------------------       --------------------
 | 
			
		||||
 *   FEDC BA98  7654 3210       0123 4567  89AB CDEF
 | 
			
		||||
 *   0001 0010  0011 0100       0010 1100  0100 1000
 | 
			
		||||
 *     0x12       0x34            0x34       0x12
 | 
			
		||||
 */
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint16_t code;
 | 
			
		||||
    struct action_kind {
 | 
			
		||||
        uint16_t param  :12;
 | 
			
		||||
        uint8_t  id     :4;
 | 
			
		||||
    } kind;
 | 
			
		||||
    struct action_key {
 | 
			
		||||
        uint8_t  code   :8;
 | 
			
		||||
        uint8_t  mods   :4;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } key;
 | 
			
		||||
    struct action_layer_bitop {
 | 
			
		||||
        uint8_t  bits   :4;
 | 
			
		||||
        uint8_t  xbit   :1;
 | 
			
		||||
        uint8_t  part   :3;
 | 
			
		||||
        uint8_t  on     :2;
 | 
			
		||||
        uint8_t  op     :2;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } layer_bitop;
 | 
			
		||||
    struct action_layer_tap {
 | 
			
		||||
        uint8_t  code   :8;
 | 
			
		||||
        uint8_t  val    :5;
 | 
			
		||||
        uint8_t  kind   :3;
 | 
			
		||||
    } layer_tap;
 | 
			
		||||
    struct action_usage {
 | 
			
		||||
        uint16_t code   :10;
 | 
			
		||||
        uint8_t  page   :2;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } usage;
 | 
			
		||||
    struct action_backlight {
 | 
			
		||||
        uint8_t  level  :8;
 | 
			
		||||
        uint8_t  opt    :4;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } backlight;
 | 
			
		||||
    struct action_command {
 | 
			
		||||
        uint8_t  id     :8;
 | 
			
		||||
        uint8_t  opt    :4;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } command;
 | 
			
		||||
    struct action_function {
 | 
			
		||||
        uint8_t  id     :8;
 | 
			
		||||
        uint8_t  opt    :4;
 | 
			
		||||
        uint8_t  kind   :4;
 | 
			
		||||
    } func;
 | 
			
		||||
} action_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* action utility */
 | 
			
		||||
#define ACTION_NO                       0
 | 
			
		||||
#define ACTION_TRANSPARENT              1
 | 
			
		||||
#define ACTION(kind, param)             ((kind)<<12 | (param))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Key Actions
 | 
			
		||||
 */
 | 
			
		||||
/* Mod bits:    43210
 | 
			
		||||
 *   bit 0      ||||+- Control
 | 
			
		||||
 *   bit 1      |||+-- Shift
 | 
			
		||||
 *   bit 2      ||+--- Alt
 | 
			
		||||
 *   bit 3      |+---- Gui
 | 
			
		||||
 *   bit 4      +----- LR flag(Left:0, Right:1)
 | 
			
		||||
 */
 | 
			
		||||
enum mods_bit {
 | 
			
		||||
    MOD_LCTL = 0x01,
 | 
			
		||||
    MOD_LSFT = 0x02,
 | 
			
		||||
    MOD_LALT = 0x04,
 | 
			
		||||
    MOD_LGUI = 0x08,
 | 
			
		||||
    MOD_RCTL = 0x11,
 | 
			
		||||
    MOD_RSFT = 0x12,
 | 
			
		||||
    MOD_RALT = 0x14,
 | 
			
		||||
    MOD_RGUI = 0x18,
 | 
			
		||||
};
 | 
			
		||||
enum mods_codes {
 | 
			
		||||
    MODS_ONESHOT = 0x00,
 | 
			
		||||
    MODS_TAP_TOGGLE = 0x01,
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_KEY(key)                 ACTION(ACT_MODS, (key))
 | 
			
		||||
#define ACTION_MODS(mods)               ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0)
 | 
			
		||||
#define ACTION_MODS_KEY(mods, key)      ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key))
 | 
			
		||||
#define ACTION_MODS_TAP_KEY(mods, key)  ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key))
 | 
			
		||||
#define ACTION_MODS_ONESHOT(mods)       ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT)
 | 
			
		||||
#define ACTION_MODS_TAP_TOGGLE(mods)    ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Other Keys
 | 
			
		||||
 */
 | 
			
		||||
enum usage_pages {
 | 
			
		||||
    PAGE_SYSTEM,
 | 
			
		||||
    PAGE_CONSUMER
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_USAGE_SYSTEM(id)         ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
 | 
			
		||||
#define ACTION_USAGE_CONSUMER(id)       ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
 | 
			
		||||
#define ACTION_MOUSEKEY(key)            ACTION(ACT_MOUSEKEY, key)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Layer Actions
 | 
			
		||||
 */
 | 
			
		||||
enum layer_param_on {
 | 
			
		||||
    ON_PRESS    = 1,
 | 
			
		||||
    ON_RELEASE  = 2,
 | 
			
		||||
    ON_BOTH     = 3,
 | 
			
		||||
};
 | 
			
		||||
enum layer_param_bit_op {
 | 
			
		||||
    OP_BIT_AND = 0,
 | 
			
		||||
    OP_BIT_OR  = 1,
 | 
			
		||||
    OP_BIT_XOR = 2,
 | 
			
		||||
    OP_BIT_SET = 3,
 | 
			
		||||
};
 | 
			
		||||
enum layer_pram_tap_op {
 | 
			
		||||
    OP_TAP_TOGGLE = 0xF0,
 | 
			
		||||
    OP_ON_OFF,
 | 
			
		||||
    OP_OFF_ON,
 | 
			
		||||
    OP_SET_CLEAR,
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_LAYER_BITOP(op, part, bits, on)      (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
 | 
			
		||||
#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))
 | 
			
		||||
/* Layer Operation */
 | 
			
		||||
#define ACTION_LAYER_CLEAR(on)                      ACTION_LAYER_BIT_AND(0, 0, (on))
 | 
			
		||||
#define ACTION_LAYER_MOMENTARY(layer)               ACTION_LAYER_ON_OFF(layer)
 | 
			
		||||
#define ACTION_LAYER_TOGGLE(layer)                  ACTION_LAYER_INVERT(layer, ON_RELEASE)
 | 
			
		||||
#define ACTION_LAYER_INVERT(layer, on)              ACTION_LAYER_BIT_XOR((layer)/4,   1<<((layer)%4),  (on))
 | 
			
		||||
#define ACTION_LAYER_ON(layer, on)                  ACTION_LAYER_BIT_OR( (layer)/4,   1<<((layer)%4),  (on))
 | 
			
		||||
#define ACTION_LAYER_OFF(layer, on)                 ACTION_LAYER_BIT_AND((layer)/4, ~(1<<((layer)%4)), (on))
 | 
			
		||||
#define ACTION_LAYER_SET(layer, on)                 ACTION_LAYER_BIT_SET((layer)/4,   1<<((layer)%4),  (on))
 | 
			
		||||
#define ACTION_LAYER_ON_OFF(layer)                  ACTION_LAYER_TAP((layer), OP_ON_OFF)
 | 
			
		||||
#define ACTION_LAYER_OFF_ON(layer)                  ACTION_LAYER_TAP((layer), OP_OFF_ON)
 | 
			
		||||
#define ACTION_LAYER_SET_CLEAR(layer)               ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
 | 
			
		||||
#define ACTION_LAYER_MODS(layer, mods)              ACTION_LAYER_TAP((layer), 0xe0 | (mods)&0x0f)
 | 
			
		||||
/* With Tapping */
 | 
			
		||||
#define ACTION_LAYER_TAP_KEY(layer, key)            ACTION_LAYER_TAP((layer), (key))
 | 
			
		||||
#define ACTION_LAYER_TAP_TOGGLE(layer)              ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
 | 
			
		||||
/* Bitwise Operation */
 | 
			
		||||
#define ACTION_LAYER_BIT_AND(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_OR( part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_OR,  (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_XOR(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_SET(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
 | 
			
		||||
/* Default Layer Bitwise Operation */
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits)    ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_OR( part, bits)    ACTION_LAYER_BITOP(OP_BIT_OR,  (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits)    ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits)    ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Extensions
 | 
			
		||||
 */
 | 
			
		||||
enum backlight_opt {
 | 
			
		||||
    BACKLIGHT_INCREASE = 0,
 | 
			
		||||
    BACKLIGHT_DECREASE = 1,
 | 
			
		||||
    BACKLIGHT_TOGGLE   = 2,
 | 
			
		||||
    BACKLIGHT_STEP     = 3,
 | 
			
		||||
    BACKLIGHT_LEVEL    = 4,
 | 
			
		||||
};
 | 
			
		||||
/* Macro */
 | 
			
		||||
#define ACTION_MACRO(id)                ACTION(ACT_MACRO, (id))
 | 
			
		||||
#define ACTION_MACRO_TAP(id)            ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
 | 
			
		||||
#define ACTION_MACRO_OPT(id, opt)       ACTION(ACT_MACRO, (opt)<<8 | (id))
 | 
			
		||||
/* Backlight */
 | 
			
		||||
#define ACTION_BACKLIGHT_INCREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
 | 
			
		||||
#define ACTION_BACKLIGHT_DECREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
 | 
			
		||||
#define ACTION_BACKLIGHT_TOGGLE()       ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
 | 
			
		||||
#define ACTION_BACKLIGHT_STEP()         ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
 | 
			
		||||
#define ACTION_BACKLIGHT_LEVEL(level)   ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | level)
 | 
			
		||||
/* Command */
 | 
			
		||||
#define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (addr))
 | 
			
		||||
/* Function */
 | 
			
		||||
enum function_opts {
 | 
			
		||||
    FUNC_TAP = 0x8,     /* indciates function is tappable */
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_FUNCTION(id)             ACTION(ACT_FUNCTION, (id))
 | 
			
		||||
#define ACTION_FUNCTION_TAP(id)         ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
 | 
			
		||||
#define ACTION_FUNCTION_OPT(id, opt)    ACTION(ACT_FUNCTION, (opt)<<8 | (id))
 | 
			
		||||
 | 
			
		||||
#endif /* ACTION_CODE_H */
 | 
			
		||||
							
								
								
									
										138
									
								
								common/action_layer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								common/action_layer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,138 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Default Layer State
 | 
			
		||||
 */
 | 
			
		||||
uint32_t default_layer_state = 0;
 | 
			
		||||
 | 
			
		||||
static void default_layer_state_set(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    debug("default_layer_state: ");
 | 
			
		||||
    default_layer_debug(); debug(" to ");
 | 
			
		||||
    default_layer_state = state;
 | 
			
		||||
    default_layer_debug(); debug("\n");
 | 
			
		||||
    clear_keyboard_but_mods(); // To avoid stuck keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void default_layer_debug(void)
 | 
			
		||||
{
 | 
			
		||||
    dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void default_layer_set(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    default_layer_state_set(state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
void default_layer_or(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    default_layer_state_set(default_layer_state | state);
 | 
			
		||||
}
 | 
			
		||||
void default_layer_and(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    default_layer_state_set(default_layer_state & state);
 | 
			
		||||
}
 | 
			
		||||
void default_layer_xor(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    default_layer_state_set(default_layer_state ^ state);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
/* 
 | 
			
		||||
 * Keymap Layer State
 | 
			
		||||
 */
 | 
			
		||||
uint32_t layer_state = 0;
 | 
			
		||||
 | 
			
		||||
static void layer_state_set(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    dprint("layer_state: ");
 | 
			
		||||
    layer_debug(); dprint(" to ");
 | 
			
		||||
    layer_state = state;
 | 
			
		||||
    layer_debug(); dprintln();
 | 
			
		||||
    clear_keyboard_but_mods(); // To avoid stuck keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_move(uint8_t layer)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(1UL<<layer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_on(uint8_t layer)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state | (1UL<<layer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_off(uint8_t layer)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state & ~(1UL<<layer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_invert(uint8_t layer)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state ^ (1UL<<layer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_or(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state | state);
 | 
			
		||||
}
 | 
			
		||||
void layer_and(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state & state);
 | 
			
		||||
}
 | 
			
		||||
void layer_xor(uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    layer_state_set(layer_state ^ state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void layer_debug(void)
 | 
			
		||||
{
 | 
			
		||||
    dprintf("%08lX(%u)", layer_state, biton32(layer_state));
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
action_t layer_switch_get_action(keypos_t key)
 | 
			
		||||
{
 | 
			
		||||
    action_t action;
 | 
			
		||||
    action.code = ACTION_TRANSPARENT;
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
    uint32_t layers = layer_state | default_layer_state;
 | 
			
		||||
    /* check top layer first */
 | 
			
		||||
    for (int8_t i = 31; i >= 0; i--) {
 | 
			
		||||
        if (layers & (1UL<<i)) {
 | 
			
		||||
            action = action_for_key(i, key);
 | 
			
		||||
            if (action.code != ACTION_TRANSPARENT) {
 | 
			
		||||
                return action;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* fall back to layer 0 */
 | 
			
		||||
    action = action_for_key(0, key);
 | 
			
		||||
    return action;
 | 
			
		||||
#else
 | 
			
		||||
    action = action_for_key(biton32(default_layer_state), key);
 | 
			
		||||
    return action;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								common/action_layer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								common/action_layer.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_LAYER_H
 | 
			
		||||
#define ACTION_LAYER_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Default Layer
 | 
			
		||||
 */
 | 
			
		||||
extern uint32_t default_layer_state;
 | 
			
		||||
void default_layer_debug(void);
 | 
			
		||||
void default_layer_set(uint32_t state);
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
/* bitwise operation */
 | 
			
		||||
void default_layer_or(uint32_t state);
 | 
			
		||||
void default_layer_and(uint32_t state);
 | 
			
		||||
void default_layer_xor(uint32_t state);
 | 
			
		||||
#else
 | 
			
		||||
#define default_layer_or(state)
 | 
			
		||||
#define default_layer_and(state)
 | 
			
		||||
#define default_layer_xor(state)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Keymap Layer
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
extern uint32_t layer_state;
 | 
			
		||||
void layer_debug(void);
 | 
			
		||||
void layer_clear(void);
 | 
			
		||||
void layer_move(uint8_t layer);
 | 
			
		||||
void layer_on(uint8_t layer);
 | 
			
		||||
void layer_off(uint8_t layer);
 | 
			
		||||
void layer_invert(uint8_t layer);
 | 
			
		||||
/* bitwise operation */
 | 
			
		||||
void layer_or(uint32_t state);
 | 
			
		||||
void layer_and(uint32_t state);
 | 
			
		||||
void layer_xor(uint32_t state);
 | 
			
		||||
#else
 | 
			
		||||
#define layer_state             0
 | 
			
		||||
#define layer_clear()
 | 
			
		||||
#define layer_move(layer)
 | 
			
		||||
#define layer_on(layer)
 | 
			
		||||
#define layer_off(layer)
 | 
			
		||||
#define layer_invert(layer)
 | 
			
		||||
 | 
			
		||||
#define layer_or(state)
 | 
			
		||||
#define layer_and(state)
 | 
			
		||||
#define layer_xor(state)
 | 
			
		||||
#define layer_debug()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* return action depending on current layer status */
 | 
			
		||||
action_t layer_switch_get_action(keypos_t key);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										83
									
								
								common/action_macro.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								common/action_macro.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_MACRO
 | 
			
		||||
 | 
			
		||||
#define MACRO_READ()  (macro = MACRO_GET(macro_p++))
 | 
			
		||||
void action_macro_play(const macro_t *macro_p)
 | 
			
		||||
{
 | 
			
		||||
    macro_t macro = END;
 | 
			
		||||
    uint8_t interval = 0;
 | 
			
		||||
 | 
			
		||||
    if (!macro_p) return;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        switch (MACRO_READ()) {
 | 
			
		||||
            case KEY_DOWN:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("KEY_DOWN(%02X)\n", macro);
 | 
			
		||||
                if (IS_MOD(macro)) {
 | 
			
		||||
                    add_weak_mods(MOD_BIT(macro));
 | 
			
		||||
                } else {
 | 
			
		||||
                    register_code(macro);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_UP:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("KEY_UP(%02X)\n", macro);
 | 
			
		||||
                if (IS_MOD(macro)) {
 | 
			
		||||
                    del_weak_mods(MOD_BIT(macro));
 | 
			
		||||
                } else {
 | 
			
		||||
                    unregister_code(macro);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case WAIT:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("WAIT(%u)\n", macro);
 | 
			
		||||
                { uint8_t ms = macro; while (ms--) wait_ms(1); }
 | 
			
		||||
                break;
 | 
			
		||||
            case INTERVAL:
 | 
			
		||||
                interval = MACRO_READ();
 | 
			
		||||
                dprintf("INTERVAL(%u)\n", interval);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x04 ... 0x73:
 | 
			
		||||
                dprintf("DOWN(%02X)\n", macro);
 | 
			
		||||
                register_code(macro);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x84 ... 0xF3:
 | 
			
		||||
                dprintf("UP(%02X)\n", macro);
 | 
			
		||||
                unregister_code(macro&0x7F);
 | 
			
		||||
                break;
 | 
			
		||||
            case END:
 | 
			
		||||
            default:
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
        // interval
 | 
			
		||||
        { uint8_t ms = interval; while (ms--) wait_ms(1); }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										102
									
								
								common/action_macro.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								common/action_macro.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,102 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_MACRO_H
 | 
			
		||||
#define ACTION_MACRO_H
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "progmem.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MACRO_NONE      0
 | 
			
		||||
#define MACRO(...)      ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
 | 
			
		||||
#define MACRO_GET(p)    pgm_read_byte(p)
 | 
			
		||||
 | 
			
		||||
typedef uint8_t macro_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_MACRO
 | 
			
		||||
void action_macro_play(const macro_t *macro_p);
 | 
			
		||||
#else
 | 
			
		||||
#define action_macro_play(macro)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Macro commands
 | 
			
		||||
 *   code(0x04-73)                      // key down(1byte)
 | 
			
		||||
 *   code(0x04-73) | 0x80               // key up(1byte)
 | 
			
		||||
 *   { KEY_DOWN, code(0x04-0xff) }      // key down(2bytes)
 | 
			
		||||
 *   { KEY_UP,   code(0x04-0xff) }      // key up(2bytes)
 | 
			
		||||
 *   WAIT                               // wait milli-seconds
 | 
			
		||||
 *   INTERVAL                           // set interval between macro commands
 | 
			
		||||
 *   END                                // stop macro execution
 | 
			
		||||
 *
 | 
			
		||||
 * Ideas(Not implemented):
 | 
			
		||||
 *   modifiers
 | 
			
		||||
 *   system usage
 | 
			
		||||
 *   consumer usage
 | 
			
		||||
 *   unicode usage
 | 
			
		||||
 *   function call
 | 
			
		||||
 *   conditionals
 | 
			
		||||
 *   loop
 | 
			
		||||
 */
 | 
			
		||||
enum macro_command_id{
 | 
			
		||||
    /* 0x00 - 0x03 */
 | 
			
		||||
    END                 = 0x00,
 | 
			
		||||
    KEY_DOWN,
 | 
			
		||||
    KEY_UP,
 | 
			
		||||
 | 
			
		||||
    /* 0x04 - 0x73 (reserved for keycode down) */
 | 
			
		||||
 | 
			
		||||
    /* 0x74 - 0x83 */
 | 
			
		||||
    WAIT                = 0x74,
 | 
			
		||||
    INTERVAL,
 | 
			
		||||
 | 
			
		||||
    /* 0x84 - 0xf3 (reserved for keycode up) */
 | 
			
		||||
 | 
			
		||||
    /* 0xf4 - 0xff */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* TODO: keycode:0x04-0x73 can be handled by 1byte command  else 2bytes are needed
 | 
			
		||||
 * if keycode between 0x04 and 0x73
 | 
			
		||||
 *      keycode / (keycode|0x80)
 | 
			
		||||
 * else
 | 
			
		||||
 *      {KEY_DOWN, keycode} / {KEY_UP, keycode}
 | 
			
		||||
*/
 | 
			
		||||
#define DOWN(key)       KEY_DOWN, (key)
 | 
			
		||||
#define UP(key)         KEY_UP, (key)
 | 
			
		||||
#define TYPE(key)       DOWN(key), UP(key)
 | 
			
		||||
#define WAIT(ms)        WAIT, (ms)
 | 
			
		||||
#define INTERVAL(ms)    INTERVAL, (ms)
 | 
			
		||||
 | 
			
		||||
/* key down */
 | 
			
		||||
#define D(key)          DOWN(KC_##key)
 | 
			
		||||
/* key up */
 | 
			
		||||
#define U(key)          UP(KC_##key)
 | 
			
		||||
/* key type */
 | 
			
		||||
#define T(key)          TYPE(KC_##key)
 | 
			
		||||
/* wait */
 | 
			
		||||
#define W(ms)           WAIT(ms)
 | 
			
		||||
/* interval */
 | 
			
		||||
#define I(ms)           INTERVAL(ms)
 | 
			
		||||
 | 
			
		||||
/* for backward comaptibility */
 | 
			
		||||
#define MD(key)         DOWN(KC_##key)
 | 
			
		||||
#define MU(key)         UP(KC_##key)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* ACTION_MACRO_H */
 | 
			
		||||
							
								
								
									
										376
									
								
								common/action_tapping.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								common/action_tapping.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,376 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "action_tapping.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
 | 
			
		||||
#define IS_TAPPING()            !IS_NOEVENT(tapping_key.event)
 | 
			
		||||
#define IS_TAPPING_PRESSED()    (IS_TAPPING() && tapping_key.event.pressed)
 | 
			
		||||
#define IS_TAPPING_RELEASED()   (IS_TAPPING() && !tapping_key.event.pressed)
 | 
			
		||||
#define IS_TAPPING_KEY(k)       (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
 | 
			
		||||
#define WITHIN_TAPPING_TERM(e)  (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static keyrecord_t tapping_key = {};
 | 
			
		||||
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
 | 
			
		||||
static uint8_t waiting_buffer_head = 0;
 | 
			
		||||
static uint8_t waiting_buffer_tail = 0;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void action_tapping_process(keyrecord_t record)
 | 
			
		||||
{
 | 
			
		||||
    if (process_tapping(&record)) {
 | 
			
		||||
        if (!IS_NOEVENT(record.event)) {
 | 
			
		||||
            debug("processed: "); debug_record(record); debug("\n");
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (!waiting_buffer_enq(record)) {
 | 
			
		||||
            // clear all in case of overflow.
 | 
			
		||||
            debug("OVERFLOW: CLEAR ALL STATES\n");
 | 
			
		||||
            clear_keyboard();
 | 
			
		||||
            waiting_buffer_clear();
 | 
			
		||||
            tapping_key = (keyrecord_t){};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // process waiting_buffer
 | 
			
		||||
    if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
 | 
			
		||||
        debug("---- action_exec: process waiting_buffer -----\n");
 | 
			
		||||
    }
 | 
			
		||||
    for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
 | 
			
		||||
            debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
 | 
			
		||||
            debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!IS_NOEVENT(record.event)) {
 | 
			
		||||
        debug("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Tapping
 | 
			
		||||
 *
 | 
			
		||||
 * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
 | 
			
		||||
 *       (without interfering by typing other key)
 | 
			
		||||
 */
 | 
			
		||||
/* return true when key event is processed or consumed. */
 | 
			
		||||
bool process_tapping(keyrecord_t *keyp)
 | 
			
		||||
{
 | 
			
		||||
    keyevent_t event = keyp->event;
 | 
			
		||||
 | 
			
		||||
    // if tapping
 | 
			
		||||
    if (IS_TAPPING_PRESSED()) {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event)) {
 | 
			
		||||
            if (tapping_key.tap.count == 0) {
 | 
			
		||||
                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
 | 
			
		||||
                    // first tap!
 | 
			
		||||
                    debug("Tapping: First tap(0->1).\n");
 | 
			
		||||
                    tapping_key.tap.count = 1;
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    process_action(&tapping_key);
 | 
			
		||||
 | 
			
		||||
                    // copy tapping state
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    // enqueue
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
#if TAPPING_TERM >= 500
 | 
			
		||||
                /* Process a key typed within TAPPING_TERM
 | 
			
		||||
                 * This can register the key before settlement of tapping,
 | 
			
		||||
                 * useful for long TAPPING_TERM but may prevent fast typing.
 | 
			
		||||
                 */
 | 
			
		||||
                else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
 | 
			
		||||
                    debug("Tapping: End. No tap. Interfered by typing key\n");
 | 
			
		||||
                    process_action(&tapping_key);
 | 
			
		||||
                    tapping_key = (keyrecord_t){};
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    // enqueue
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
                /* Process release event of a key pressed before tapping starts
 | 
			
		||||
                 * Without this unexpected repeating will occur with having fast repeating setting
 | 
			
		||||
                 * https://github.com/tmk/tmk_keyboard/issues/60
 | 
			
		||||
                 */
 | 
			
		||||
                else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
 | 
			
		||||
                    // Modifier should be retained till end of this tapping.
 | 
			
		||||
                    action_t action = layer_switch_get_action(event.key);
 | 
			
		||||
                    switch (action.kind.id) {
 | 
			
		||||
                        case ACT_LMODS:
 | 
			
		||||
                        case ACT_RMODS:
 | 
			
		||||
                            if (action.key.mods && !action.key.code) return false;
 | 
			
		||||
                            if (IS_MOD(action.key.code)) return false;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case ACT_LMODS_TAP:
 | 
			
		||||
                        case ACT_RMODS_TAP:
 | 
			
		||||
                            if (action.key.mods && keyp->tap.count == 0) return false;
 | 
			
		||||
                            if (IS_MOD(action.key.code)) return false;
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                    // Release of key should be process immediately.
 | 
			
		||||
                    debug("Tapping: release event of a key pressed before tapping\n");
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    // set interrupted flag when other key preesed during tapping
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        tapping_key.tap.interrupted = true;
 | 
			
		||||
                    }
 | 
			
		||||
                    // enqueue 
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // tap_count > 0
 | 
			
		||||
            else {
 | 
			
		||||
                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
 | 
			
		||||
                    debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else if (is_tap_key(event.key) && event.pressed) {
 | 
			
		||||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_action(&(keyrecord_t){
 | 
			
		||||
                                .tap = tapping_key.tap,
 | 
			
		||||
                                .event.key = tapping_key.event.key,
 | 
			
		||||
                                .event.time = event.time,
 | 
			
		||||
                                .event.pressed = false
 | 
			
		||||
                        });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    if (!IS_NOEVENT(event)) {
 | 
			
		||||
                        debug("Tapping: key event while last tap(>0).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // after TAPPING_TERM
 | 
			
		||||
        else {
 | 
			
		||||
            if (tapping_key.tap.count == 0) {
 | 
			
		||||
                debug("Tapping: End. Timeout. Not tap(0): ");
 | 
			
		||||
                debug_event(event); debug("\n");
 | 
			
		||||
                process_action(&tapping_key);
 | 
			
		||||
                tapping_key = (keyrecord_t){};
 | 
			
		||||
                debug_tapping_key();
 | 
			
		||||
                return false;
 | 
			
		||||
            }  else {
 | 
			
		||||
                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
 | 
			
		||||
                    debug("Tapping: End. last timeout tap release(>0).");
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    tapping_key = (keyrecord_t){};
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else if (is_tap_key(event.key) && event.pressed) {
 | 
			
		||||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_action(&(keyrecord_t){
 | 
			
		||||
                                .tap = tapping_key.tap,
 | 
			
		||||
                                .event.key = tapping_key.event.key,
 | 
			
		||||
                                .event.time = event.time,
 | 
			
		||||
                                .event.pressed = false
 | 
			
		||||
                        });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last timeout tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    if (!IS_NOEVENT(event)) {
 | 
			
		||||
                        debug("Tapping: key event while last timeout tap(>0).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (IS_TAPPING_RELEASED()) {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event)) {
 | 
			
		||||
            if (event.pressed) {
 | 
			
		||||
                if (IS_TAPPING_KEY(event.key)) {
 | 
			
		||||
                    if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
 | 
			
		||||
                        // sequential tap.
 | 
			
		||||
                        keyp->tap = tapping_key.tap;
 | 
			
		||||
                        if (keyp->tap.count < 15) keyp->tap.count += 1;
 | 
			
		||||
                        debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
 | 
			
		||||
                        process_action(keyp);
 | 
			
		||||
                        tapping_key = *keyp;
 | 
			
		||||
                        debug_tapping_key();
 | 
			
		||||
                        return true;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // FIX: start new tap again
 | 
			
		||||
                        tapping_key = *keyp;
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (is_tap_key(event.key)) {
 | 
			
		||||
                    // Sequential tap can be interfered with other tap key.
 | 
			
		||||
                    debug("Tapping: Start with interfering other tap.\n");
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // should none in buffer
 | 
			
		||||
                    // FIX: interrupted when other key is pressed
 | 
			
		||||
                    tapping_key.tap.interrupted = true;
 | 
			
		||||
                    process_action(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
 | 
			
		||||
                process_action(keyp);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // FIX: process_aciton here?
 | 
			
		||||
            // timeout. no sequential tap.
 | 
			
		||||
            debug("Tapping: End(Timeout after releasing last tap): ");
 | 
			
		||||
            debug_event(event); debug("\n");
 | 
			
		||||
            tapping_key = (keyrecord_t){};
 | 
			
		||||
            debug_tapping_key();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // not tapping state
 | 
			
		||||
    else {
 | 
			
		||||
        if (event.pressed && is_tap_key(event.key)) {
 | 
			
		||||
            debug("Tapping: Start(Press tap key).\n");
 | 
			
		||||
            tapping_key = *keyp;
 | 
			
		||||
            waiting_buffer_scan_tap();
 | 
			
		||||
            debug_tapping_key();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            process_action(keyp);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Waiting buffer
 | 
			
		||||
 */
 | 
			
		||||
bool waiting_buffer_enq(keyrecord_t record)
 | 
			
		||||
{
 | 
			
		||||
    if (IS_NOEVENT(record.event)) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
 | 
			
		||||
        debug("waiting_buffer_enq: Over flow.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    waiting_buffer[waiting_buffer_head] = record;
 | 
			
		||||
    waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
 | 
			
		||||
 | 
			
		||||
    debug("waiting_buffer_enq: "); debug_waiting_buffer();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void waiting_buffer_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    waiting_buffer_head = 0;
 | 
			
		||||
    waiting_buffer_tail = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool waiting_buffer_typed(keyevent_t event)
 | 
			
		||||
{
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed !=  waiting_buffer[i].event.pressed) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    // tapping already is settled
 | 
			
		||||
    if (tapping_key.tap.count > 0) return;
 | 
			
		||||
    // invalid state: tapping_key released && tap.count == 0
 | 
			
		||||
    if (!tapping_key.event.pressed) return;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
 | 
			
		||||
                !waiting_buffer[i].event.pressed &&
 | 
			
		||||
                WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
 | 
			
		||||
            tapping_key.tap.count = 1;
 | 
			
		||||
            waiting_buffer[i].tap.count = 1;
 | 
			
		||||
            process_action(&tapping_key);
 | 
			
		||||
 | 
			
		||||
            debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
 | 
			
		||||
            debug_waiting_buffer();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * debug print
 | 
			
		||||
 */
 | 
			
		||||
static void debug_tapping_key(void)
 | 
			
		||||
{
 | 
			
		||||
    debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void debug_waiting_buffer(void)
 | 
			
		||||
{
 | 
			
		||||
    debug("{ ");
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
 | 
			
		||||
    }
 | 
			
		||||
    debug("}\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										39
									
								
								common/action_tapping.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								common/action_tapping.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_TAPPING_H
 | 
			
		||||
#define ACTION_TAPPING_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* period of tapping(ms) */
 | 
			
		||||
#ifndef TAPPING_TERM
 | 
			
		||||
#define TAPPING_TERM    200
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* tap count needed for toggling a feature */
 | 
			
		||||
#ifndef TAPPING_TOGGLE
 | 
			
		||||
#define TAPPING_TOGGLE  5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define WAITING_BUFFER_SIZE 8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
void action_tapping_process(keyrecord_t record);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										307
									
								
								common/action_util.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								common/action_util.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,307 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "report.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
static inline void add_key_byte(uint8_t code);
 | 
			
		||||
static inline void del_key_byte(uint8_t code);
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
static inline void add_key_bit(uint8_t code);
 | 
			
		||||
static inline void del_key_bit(uint8_t code);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint8_t real_mods = 0;
 | 
			
		||||
static uint8_t weak_mods = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef USB_6KRO_ENABLE
 | 
			
		||||
#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
 | 
			
		||||
#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
 | 
			
		||||
#define RO_INC(a) RO_ADD(a, 1)
 | 
			
		||||
#define RO_DEC(a) RO_SUB(a, 1)
 | 
			
		||||
static int8_t cb_head = 0;
 | 
			
		||||
static int8_t cb_tail = 0;
 | 
			
		||||
static int8_t cb_count = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// TODO: pointer variable is not needed
 | 
			
		||||
//report_keyboard_t keyboard_report = {};
 | 
			
		||||
report_keyboard_t *keyboard_report = &(report_keyboard_t){};
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
static int8_t oneshot_mods = 0;
 | 
			
		||||
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
static int16_t oneshot_time = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void send_keyboard_report(void) {
 | 
			
		||||
    keyboard_report->mods  = real_mods;
 | 
			
		||||
    keyboard_report->mods |= weak_mods;
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
    if (oneshot_mods) {
 | 
			
		||||
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
 | 
			
		||||
            dprintf("Oneshot: timeout\n");
 | 
			
		||||
            clear_oneshot_mods();
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        keyboard_report->mods |= oneshot_mods;
 | 
			
		||||
        if (has_anykey()) {
 | 
			
		||||
            clear_oneshot_mods();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    host_keyboard_send(keyboard_report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* key */
 | 
			
		||||
void add_key(uint8_t key)
 | 
			
		||||
{
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_nkro) {
 | 
			
		||||
        add_key_bit(key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    add_key_byte(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void del_key(uint8_t key)
 | 
			
		||||
{
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_nkro) {
 | 
			
		||||
        del_key_bit(key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    del_key_byte(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_keys(void)
 | 
			
		||||
{
 | 
			
		||||
    // not clear mods
 | 
			
		||||
    for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
 | 
			
		||||
        keyboard_report->raw[i] = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* modifier */
 | 
			
		||||
uint8_t get_mods(void) { return real_mods; }
 | 
			
		||||
void add_mods(uint8_t mods) { real_mods |= mods; }
 | 
			
		||||
void del_mods(uint8_t mods) { real_mods &= ~mods; }
 | 
			
		||||
void set_mods(uint8_t mods) { real_mods = mods; }
 | 
			
		||||
void clear_mods(void) { real_mods = 0; }
 | 
			
		||||
 | 
			
		||||
/* weak modifier */
 | 
			
		||||
uint8_t get_weak_mods(void) { return weak_mods; }
 | 
			
		||||
void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
 | 
			
		||||
void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
 | 
			
		||||
void set_weak_mods(uint8_t mods) { weak_mods = mods; }
 | 
			
		||||
void clear_weak_mods(void) { weak_mods = 0; }
 | 
			
		||||
 | 
			
		||||
/* Oneshot modifier */
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
void set_oneshot_mods(uint8_t mods)
 | 
			
		||||
{
 | 
			
		||||
    oneshot_mods = mods;
 | 
			
		||||
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
    oneshot_time = timer_read();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
void clear_oneshot_mods(void)
 | 
			
		||||
{
 | 
			
		||||
    oneshot_mods = 0;
 | 
			
		||||
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
    oneshot_time = 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * inspect keyboard state
 | 
			
		||||
 */
 | 
			
		||||
uint8_t has_anykey(void)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t cnt = 0;
 | 
			
		||||
    for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
 | 
			
		||||
        if (keyboard_report->raw[i])
 | 
			
		||||
            cnt++;
 | 
			
		||||
    }
 | 
			
		||||
    return cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t has_anymod(void)
 | 
			
		||||
{
 | 
			
		||||
    return bitpop(real_mods);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t get_first_key(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_nkro) {
 | 
			
		||||
        uint8_t i = 0;
 | 
			
		||||
        for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
 | 
			
		||||
            ;
 | 
			
		||||
        return i<<3 | biton(keyboard_report->nkro.bits[i]);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USB_6KRO_ENABLE
 | 
			
		||||
    uint8_t i = cb_head;
 | 
			
		||||
    do {
 | 
			
		||||
        if (keyboard_report->keys[i] != 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        i = RO_INC(i);
 | 
			
		||||
    } while (i != cb_tail);
 | 
			
		||||
    return keyboard_report->keys[i];
 | 
			
		||||
#else
 | 
			
		||||
    return keyboard_report->keys[0];
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* local functions */
 | 
			
		||||
static inline void add_key_byte(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USB_6KRO_ENABLE
 | 
			
		||||
    int8_t i = cb_head;
 | 
			
		||||
    int8_t empty = -1;
 | 
			
		||||
    if (cb_count) {
 | 
			
		||||
        do {
 | 
			
		||||
            if (keyboard_report->keys[i] == code) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (empty == -1 && keyboard_report->keys[i] == 0) {
 | 
			
		||||
                empty = i;
 | 
			
		||||
            }
 | 
			
		||||
            i = RO_INC(i);
 | 
			
		||||
        } while (i != cb_tail);
 | 
			
		||||
        if (i == cb_tail) {
 | 
			
		||||
            if (cb_tail == cb_head) {
 | 
			
		||||
                // buffer is full
 | 
			
		||||
                if (empty == -1) {
 | 
			
		||||
                    // pop head when has no empty space
 | 
			
		||||
                    cb_head = RO_INC(cb_head);
 | 
			
		||||
                    cb_count--;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    // left shift when has empty space
 | 
			
		||||
                    uint8_t offset = 1;
 | 
			
		||||
                    i = RO_INC(empty);
 | 
			
		||||
                    do {
 | 
			
		||||
                        if (keyboard_report->keys[i] != 0) {
 | 
			
		||||
                            keyboard_report->keys[empty] = keyboard_report->keys[i];
 | 
			
		||||
                            keyboard_report->keys[i] = 0;
 | 
			
		||||
                            empty = RO_INC(empty);
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            offset++;
 | 
			
		||||
                        }
 | 
			
		||||
                        i = RO_INC(i);
 | 
			
		||||
                    } while (i != cb_tail);
 | 
			
		||||
                    cb_tail = RO_SUB(cb_tail, offset);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // add to tail
 | 
			
		||||
    keyboard_report->keys[cb_tail] = code;
 | 
			
		||||
    cb_tail = RO_INC(cb_tail);
 | 
			
		||||
    cb_count++;
 | 
			
		||||
#else
 | 
			
		||||
    int8_t i = 0;
 | 
			
		||||
    int8_t empty = -1;
 | 
			
		||||
    for (; i < KEYBOARD_REPORT_KEYS; i++) {
 | 
			
		||||
        if (keyboard_report->keys[i] == code) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (empty == -1 && keyboard_report->keys[i] == 0) {
 | 
			
		||||
            empty = i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (i == KEYBOARD_REPORT_KEYS) {
 | 
			
		||||
        if (empty != -1) {
 | 
			
		||||
            keyboard_report->keys[empty] = code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void del_key_byte(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USB_6KRO_ENABLE
 | 
			
		||||
    uint8_t i = cb_head;
 | 
			
		||||
    if (cb_count) {
 | 
			
		||||
        do {
 | 
			
		||||
            if (keyboard_report->keys[i] == code) {
 | 
			
		||||
                keyboard_report->keys[i] = 0;
 | 
			
		||||
                cb_count--;
 | 
			
		||||
                if (cb_count == 0) {
 | 
			
		||||
                    // reset head and tail
 | 
			
		||||
                    cb_tail = cb_head = 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (i == RO_DEC(cb_tail)) {
 | 
			
		||||
                    // left shift when next to tail
 | 
			
		||||
                    do {
 | 
			
		||||
                        cb_tail = RO_DEC(cb_tail);
 | 
			
		||||
                        if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    } while (cb_tail != cb_head);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            i = RO_INC(i);
 | 
			
		||||
        } while (i != cb_tail);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
 | 
			
		||||
        if (keyboard_report->keys[i] == code) {
 | 
			
		||||
            keyboard_report->keys[i] = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
static inline void add_key_bit(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if ((code>>3) < KEYBOARD_REPORT_BITS) {
 | 
			
		||||
        keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
 | 
			
		||||
    } else {
 | 
			
		||||
        dprintf("add_key_bit: can't add: %02X\n", code);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void del_key_bit(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if ((code>>3) < KEYBOARD_REPORT_BITS) {
 | 
			
		||||
        keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
 | 
			
		||||
    } else {
 | 
			
		||||
        dprintf("del_key_bit: can't del: %02X\n", code);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										66
									
								
								common/action_util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								common/action_util.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ACTION_UTIL_H
 | 
			
		||||
#define ACTION_UTIL_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "report.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern report_keyboard_t *keyboard_report;
 | 
			
		||||
 | 
			
		||||
void send_keyboard_report(void);
 | 
			
		||||
 | 
			
		||||
/* key */
 | 
			
		||||
void add_key(uint8_t key);
 | 
			
		||||
void del_key(uint8_t key);
 | 
			
		||||
void clear_keys(void);
 | 
			
		||||
 | 
			
		||||
/* modifier */
 | 
			
		||||
uint8_t get_mods(void);
 | 
			
		||||
void add_mods(uint8_t mods);
 | 
			
		||||
void del_mods(uint8_t mods);
 | 
			
		||||
void set_mods(uint8_t mods);
 | 
			
		||||
void clear_mods(void);
 | 
			
		||||
 | 
			
		||||
/* weak modifier */
 | 
			
		||||
uint8_t get_weak_mods(void);
 | 
			
		||||
void add_weak_mods(uint8_t mods);
 | 
			
		||||
void del_weak_mods(uint8_t mods);
 | 
			
		||||
void set_weak_mods(uint8_t mods);
 | 
			
		||||
void clear_weak_mods(void);
 | 
			
		||||
 | 
			
		||||
/* oneshot modifier */
 | 
			
		||||
void set_oneshot_mods(uint8_t mods);
 | 
			
		||||
void clear_oneshot_mods(void);
 | 
			
		||||
void oneshot_toggle(void);
 | 
			
		||||
void oneshot_enable(void);
 | 
			
		||||
void oneshot_disable(void);
 | 
			
		||||
 | 
			
		||||
/* inspect */
 | 
			
		||||
uint8_t has_anykey(void);
 | 
			
		||||
uint8_t has_anymod(void);
 | 
			
		||||
uint8_t get_first_key(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										148
									
								
								common/avr/bootloader.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								common/avr/bootloader.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,148 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
#include <LUFA/Drivers/USB/USB.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Boot Section Size in *BYTEs*
 | 
			
		||||
 *   Teensy   halfKay    512
 | 
			
		||||
 *   Teensy++ halfKay    1024
 | 
			
		||||
 *   Atmel DFU loader    4096
 | 
			
		||||
 *   LUFA bootloader     4096
 | 
			
		||||
 *   USBaspLoader        2048
 | 
			
		||||
 */
 | 
			
		||||
#ifndef BOOTLOADER_SIZE
 | 
			
		||||
#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
 | 
			
		||||
#define BOOTLOADER_SIZE     4096
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define FLASH_SIZE          (FLASHEND + 1L)
 | 
			
		||||
#define BOOTLOADER_START    (FLASH_SIZE - BOOTLOADER_SIZE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Entering the Bootloader via Software 
 | 
			
		||||
 * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
 | 
			
		||||
 */
 | 
			
		||||
#define BOOTLOADER_RESET_KEY 0xB007B007
 | 
			
		||||
uint32_t reset_key  __attribute__ ((section (".noinit")));
 | 
			
		||||
 | 
			
		||||
/* initialize MCU status by watchdog reset */
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
    USB_Disable();
 | 
			
		||||
    cli();
 | 
			
		||||
    _delay_ms(2000);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
    cli();
 | 
			
		||||
    UDCON = 1;
 | 
			
		||||
    USBCON = (1<<FRZCLK);
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // watchdog reset
 | 
			
		||||
    reset_key = BOOTLOADER_RESET_KEY;
 | 
			
		||||
    wdt_enable(WDTO_250MS);
 | 
			
		||||
    for (;;);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* this runs before main() */
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void)
 | 
			
		||||
{
 | 
			
		||||
    if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
 | 
			
		||||
        reset_key = 0;
 | 
			
		||||
 | 
			
		||||
        // My custom USBasploader requires this to come up.
 | 
			
		||||
        MCUSR = 0;
 | 
			
		||||
 | 
			
		||||
        // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
 | 
			
		||||
        MCUSR &= ~(1<<WDRF);
 | 
			
		||||
        wdt_disable();
 | 
			
		||||
 | 
			
		||||
        // This is compled into 'icall', address should be in word unit, not byte.
 | 
			
		||||
        ((void (*)(void))(BOOTLOADER_START/2))();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
/* Jumping To The Bootloader
 | 
			
		||||
 * http://www.pjrc.com/teensy/jump_to_bootloader.html
 | 
			
		||||
 * 
 | 
			
		||||
 * This method doen't work when using LUFA. idk why.
 | 
			
		||||
 * - needs to initialize more regisers or interrupt setting?
 | 
			
		||||
 */
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
    USB_Disable();
 | 
			
		||||
    cli();
 | 
			
		||||
    _delay_ms(2000);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
    cli();
 | 
			
		||||
    UDCON = 1;
 | 
			
		||||
    USBCON = (1<<FRZCLK);
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Initialize
 | 
			
		||||
     */
 | 
			
		||||
#if defined(__AVR_AT90USB162__)
 | 
			
		||||
    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
 | 
			
		||||
    TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
 | 
			
		||||
    DDRB = 0; DDRC = 0; DDRD = 0;
 | 
			
		||||
    PORTB = 0; PORTC = 0; PORTD = 0;
 | 
			
		||||
#elif defined(__AVR_ATmega32U4__)
 | 
			
		||||
    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
 | 
			
		||||
    DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
 | 
			
		||||
    PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
 | 
			
		||||
#elif defined(__AVR_AT90USB646__)
 | 
			
		||||
    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
 | 
			
		||||
    DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
 | 
			
		||||
    PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
 | 
			
		||||
#elif defined(__AVR_AT90USB1286__)
 | 
			
		||||
    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
 | 
			
		||||
    DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
 | 
			
		||||
    PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * USBaspLoader
 | 
			
		||||
     */
 | 
			
		||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
 | 
			
		||||
    // This makes custom USBasploader come up.
 | 
			
		||||
    MCUSR = 0;
 | 
			
		||||
 | 
			
		||||
    // initialize ports
 | 
			
		||||
    PORTB = 0; PORTC= 0; PORTD = 0;
 | 
			
		||||
    DDRB = 0; DDRC= 0; DDRD = 0;
 | 
			
		||||
 | 
			
		||||
    // disable interrupts
 | 
			
		||||
    EIMSK = 0; EECR = 0; SPCR = 0;
 | 
			
		||||
    ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
 | 
			
		||||
    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
 | 
			
		||||
    ADCSRA = 0; TWCR = 0; UCSR0B = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // This is compled into 'icall', address should be in word unit, not byte.
 | 
			
		||||
    ((void (*)(void))(BOOTLOADER_START/2))();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										45
									
								
								common/avr/eeconfig.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								common/avr/eeconfig.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <avr/eeprom.h>
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										122
									
								
								common/avr/suspend.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								common/avr/suspend.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,122 @@
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
#include <avr/sleep.h>
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "backlight.h"
 | 
			
		||||
#include "suspend_avr.h"
 | 
			
		||||
#include "suspend.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
#include "lufa.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define wdt_intr_enable(value)   \
 | 
			
		||||
__asm__ __volatile__ (  \
 | 
			
		||||
    "in __tmp_reg__,__SREG__" "\n\t"    \
 | 
			
		||||
    "cli" "\n\t"    \
 | 
			
		||||
    "wdr" "\n\t"    \
 | 
			
		||||
    "sts %0,%1" "\n\t"  \
 | 
			
		||||
    "out __SREG__,__tmp_reg__" "\n\t"   \
 | 
			
		||||
    "sts %0,%2" "\n\t" \
 | 
			
		||||
    : /* no outputs */  \
 | 
			
		||||
    : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
 | 
			
		||||
    "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
 | 
			
		||||
    "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
 | 
			
		||||
        _BV(WDIE) | (value & 0x07)) ) \
 | 
			
		||||
    : "r0"  \
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void suspend_idle(uint8_t time)
 | 
			
		||||
{
 | 
			
		||||
    cli();
 | 
			
		||||
    set_sleep_mode(SLEEP_MODE_IDLE);
 | 
			
		||||
    sleep_enable();
 | 
			
		||||
    sei();
 | 
			
		||||
    sleep_cpu();
 | 
			
		||||
    sleep_disable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Power down MCU with watchdog timer
 | 
			
		||||
 * wdto: watchdog timer timeout defined in <avr/wdt.h>
 | 
			
		||||
 *          WDTO_15MS
 | 
			
		||||
 *          WDTO_30MS
 | 
			
		||||
 *          WDTO_60MS
 | 
			
		||||
 *          WDTO_120MS
 | 
			
		||||
 *          WDTO_250MS
 | 
			
		||||
 *          WDTO_500MS
 | 
			
		||||
 *          WDTO_1S
 | 
			
		||||
 *          WDTO_2S
 | 
			
		||||
 *          WDTO_4S
 | 
			
		||||
 *          WDTO_8S
 | 
			
		||||
 */
 | 
			
		||||
static uint8_t wdt_timeout = 0;
 | 
			
		||||
static void power_down(uint8_t wdto)
 | 
			
		||||
{
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
    if (USB_DeviceState == DEVICE_STATE_Configured) return;
 | 
			
		||||
#endif
 | 
			
		||||
    wdt_timeout = wdto;
 | 
			
		||||
 | 
			
		||||
    // Watchdog Interrupt Mode
 | 
			
		||||
    wdt_intr_enable(wdto);
 | 
			
		||||
 | 
			
		||||
    // TODO: more power saving
 | 
			
		||||
    // See PicoPower application note
 | 
			
		||||
    // - I/O port input with pullup
 | 
			
		||||
    // - prescale clock
 | 
			
		||||
    // - BOD disable
 | 
			
		||||
    // - Power Reduction Register PRR
 | 
			
		||||
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 | 
			
		||||
    sleep_enable();
 | 
			
		||||
    sei();
 | 
			
		||||
    sleep_cpu();
 | 
			
		||||
    sleep_disable();
 | 
			
		||||
 | 
			
		||||
    // Disable watchdog after sleep
 | 
			
		||||
    wdt_disable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void suspend_power_down(void)
 | 
			
		||||
{
 | 
			
		||||
    power_down(WDTO_15MS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
    clear_keyboard();
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
    backlight_init();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef NO_SUSPEND_POWER_DOWN
 | 
			
		||||
/* watchdog timeout */
 | 
			
		||||
ISR(WDT_vect)
 | 
			
		||||
{
 | 
			
		||||
    // compensate timer for sleep
 | 
			
		||||
    switch (wdt_timeout) {
 | 
			
		||||
        case WDTO_15MS:
 | 
			
		||||
            timer_count += 15 + 2;  // WDTO_15MS + 2(from observation)
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										27
									
								
								common/avr/suspend_avr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								common/avr/suspend_avr.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
#ifndef SUSPEND_AVR_H
 | 
			
		||||
#define SUSPEND_AVR_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <avr/sleep.h>
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define wdt_intr_enable(value)   \
 | 
			
		||||
__asm__ __volatile__ (  \
 | 
			
		||||
    "in __tmp_reg__,__SREG__" "\n\t"    \
 | 
			
		||||
    "cli" "\n\t"    \
 | 
			
		||||
    "wdr" "\n\t"    \
 | 
			
		||||
    "sts %0,%1" "\n\t"  \
 | 
			
		||||
    "out __SREG__,__tmp_reg__" "\n\t"   \
 | 
			
		||||
    "sts %0,%2" "\n\t" \
 | 
			
		||||
    : /* no outputs */  \
 | 
			
		||||
    : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
 | 
			
		||||
    "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
 | 
			
		||||
    "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
 | 
			
		||||
        _BV(WDIE) | (value & 0x07)) ) \
 | 
			
		||||
    : "r0"  \
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										117
									
								
								common/avr/timer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								common/avr/timer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "timer_avr.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// counter resolution 1ms
 | 
			
		||||
// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
 | 
			
		||||
volatile uint32_t timer_count = 0;
 | 
			
		||||
 | 
			
		||||
void timer_init(void)
 | 
			
		||||
{
 | 
			
		||||
    // Timer0 CTC mode
 | 
			
		||||
    TCCR0A = 0x02;
 | 
			
		||||
 | 
			
		||||
#if TIMER_PRESCALER == 1
 | 
			
		||||
    TCCR0B = 0x01;
 | 
			
		||||
#elif TIMER_PRESCALER == 8
 | 
			
		||||
    TCCR0B = 0x02;
 | 
			
		||||
#elif TIMER_PRESCALER == 64
 | 
			
		||||
    TCCR0B = 0x03;
 | 
			
		||||
#elif TIMER_PRESCALER == 256
 | 
			
		||||
    TCCR0B = 0x04;
 | 
			
		||||
#elif TIMER_PRESCALER == 1024
 | 
			
		||||
    TCCR0B = 0x05;
 | 
			
		||||
#else
 | 
			
		||||
#   error "Timer prescaler value is NOT vaild."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    OCR0A = TIMER_RAW_TOP;
 | 
			
		||||
    TIMSK0 = (1<<OCIE0A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void timer_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    timer_count = 0;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint16_t timer_read(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t t;
 | 
			
		||||
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    t = timer_count;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
 | 
			
		||||
    return (t & 0xFFFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint32_t timer_read32(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t t;
 | 
			
		||||
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    t = timer_count;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint16_t timer_elapsed(uint16_t last)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t t;
 | 
			
		||||
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    t = timer_count;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
 | 
			
		||||
    return TIMER_DIFF_16((t & 0xFFFF), last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint32_t timer_elapsed32(uint32_t last)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t t;
 | 
			
		||||
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    t = timer_count;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
 | 
			
		||||
    return TIMER_DIFF_32(t, last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// excecuted once per 1ms.(excess for just timer count?)
 | 
			
		||||
ISR(TIMER0_COMPA_vect)
 | 
			
		||||
{
 | 
			
		||||
    timer_count++;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								common/avr/timer_avr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								common/avr/timer_avr.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef TIMER_AVR_H
 | 
			
		||||
#define TIMER_AVR_H 1
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#ifndef TIMER_PRESCALER
 | 
			
		||||
#   if F_CPU > 16000000
 | 
			
		||||
#       define TIMER_PRESCALER      256
 | 
			
		||||
#   elif F_CPU > 2000000
 | 
			
		||||
#       define TIMER_PRESCALER      64
 | 
			
		||||
#   elif F_CPU > 250000
 | 
			
		||||
#       define TIMER_PRESCALER      8
 | 
			
		||||
#   else
 | 
			
		||||
#       define TIMER_PRESCALER      1
 | 
			
		||||
#   endif
 | 
			
		||||
#endif
 | 
			
		||||
#define TIMER_RAW_FREQ      (F_CPU/TIMER_PRESCALER)
 | 
			
		||||
#define TIMER_RAW           TCNT0
 | 
			
		||||
#define TIMER_RAW_TOP       (TIMER_RAW_FREQ/1000)
 | 
			
		||||
 | 
			
		||||
#if (TIMER_RAW_TOP > 255)
 | 
			
		||||
#   error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										500
									
								
								common/avr/xprintf.S
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										500
									
								
								common/avr/xprintf.S
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,500 @@
 | 
			
		|||
;---------------------------------------------------------------------------;
 | 
			
		||||
; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011
 | 
			
		||||
;---------------------------------------------------------------------------;
 | 
			
		||||
 | 
			
		||||
				// Base size is 152 bytes
 | 
			
		||||
#define	CR_CRLF		0	// Convert \n to \r\n (+10 bytes)
 | 
			
		||||
#define USE_XPRINTF	1	// Enable xprintf function (+194 bytes)
 | 
			
		||||
#define USE_XSPRINTF	0	// Add xsprintf function (+78 bytes)
 | 
			
		||||
#define USE_XFPRINTF	0	// Add xfprintf function (+54 bytes)
 | 
			
		||||
#define USE_XATOI	0	// Enable xatoi function (+182 bytes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if FLASHEND > 0x1FFFF
 | 
			
		||||
#error xitoa module does not support 256K devices
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
.nolist
 | 
			
		||||
#include <avr/io.h>	// Include device specific definitions.
 | 
			
		||||
.list
 | 
			
		||||
 | 
			
		||||
#ifdef SPM_PAGESIZE	// Recent devices have "lpm Rd,Z+" and "movw".
 | 
			
		||||
.macro	_LPMI	reg
 | 
			
		||||
	lpm	\reg, Z+
 | 
			
		||||
.endm
 | 
			
		||||
.macro	_MOVW	dh,dl, sh,sl
 | 
			
		||||
	movw	\dl, \sl
 | 
			
		||||
.endm
 | 
			
		||||
#else			// Earlier devices do not have "lpm Rd,Z+" nor "movw".
 | 
			
		||||
.macro	_LPMI	reg
 | 
			
		||||
	lpm
 | 
			
		||||
	mov	\reg, r0
 | 
			
		||||
	adiw	ZL, 1
 | 
			
		||||
.endm
 | 
			
		||||
.macro	_MOVW	dh,dl, sh,sl
 | 
			
		||||
	mov	\dl, \sl
 | 
			
		||||
	mov	\dh, \sh
 | 
			
		||||
.endm
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;---------------------------------------------------------------------------
 | 
			
		||||
; Stub function to forward to user output function
 | 
			
		||||
;
 | 
			
		||||
;Prototype: void xputc (char chr	// a character to be output
 | 
			
		||||
;			);
 | 
			
		||||
;Size: 12/12 words
 | 
			
		||||
 | 
			
		||||
.section .bss
 | 
			
		||||
.global xfunc_out	; xfunc_out must be initialized before using this module.
 | 
			
		||||
xfunc_out:	.ds.w	1
 | 
			
		||||
.section .text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.func xputc
 | 
			
		||||
.global xputc
 | 
			
		||||
xputc:
 | 
			
		||||
#if CR_CRLF
 | 
			
		||||
	cpi	r24, 10		;LF --> CRLF
 | 
			
		||||
	brne	1f		;
 | 
			
		||||
	ldi	r24, 13		;
 | 
			
		||||
	rcall	1f		;
 | 
			
		||||
	ldi	r24, 10		;/
 | 
			
		||||
1:
 | 
			
		||||
#endif
 | 
			
		||||
	push	ZH
 | 
			
		||||
	push	ZL
 | 
			
		||||
	lds	ZL, xfunc_out+0	;Pointer to the registered output function.
 | 
			
		||||
	lds	ZH, xfunc_out+1	;/
 | 
			
		||||
	sbiw	ZL, 0		;Skip if null
 | 
			
		||||
	breq	2f		;/
 | 
			
		||||
	icall
 | 
			
		||||
2:	pop	ZL
 | 
			
		||||
	pop	ZH
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;---------------------------------------------------------------------------
 | 
			
		||||
; Direct ROM string output
 | 
			
		||||
;
 | 
			
		||||
;Prototype: void xputs (const char *str_p // rom string to be output
 | 
			
		||||
;			);
 | 
			
		||||
 | 
			
		||||
.func xputs
 | 
			
		||||
.global xputs
 | 
			
		||||
xputs:
 | 
			
		||||
	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string
 | 
			
		||||
1:	_LPMI	r24
 | 
			
		||||
	cpi	r24, 0
 | 
			
		||||
	breq	2f
 | 
			
		||||
	rcall	xputc
 | 
			
		||||
	rjmp	1b
 | 
			
		||||
2:	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;---------------------------------------------------------------------------
 | 
			
		||||
; Extended direct numeral string output (32bit version)
 | 
			
		||||
;
 | 
			
		||||
;Prototype: void xitoa (long value,	// value to be output
 | 
			
		||||
;                       char radix,	// radix
 | 
			
		||||
;                       char width);	// minimum width
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
.func xitoa
 | 
			
		||||
.global xitoa
 | 
			
		||||
xitoa:
 | 
			
		||||
				;r25:r22 = value, r20 = base, r18 = digits
 | 
			
		||||
	clr	r31		;r31 = stack level
 | 
			
		||||
	ldi	r30, ' '	;r30 = sign
 | 
			
		||||
	ldi	r19, ' '	;r19 = filler
 | 
			
		||||
	sbrs	r20, 7		;When base indicates signd format and the value
 | 
			
		||||
	rjmp	0f		;is minus, add a '-'.
 | 
			
		||||
	neg	r20		;
 | 
			
		||||
	sbrs	r25, 7		;
 | 
			
		||||
	rjmp	0f		;
 | 
			
		||||
	ldi	r30, '-'	;
 | 
			
		||||
	com	r22		;
 | 
			
		||||
	com	r23		;
 | 
			
		||||
	com	r24		;
 | 
			
		||||
	com	r25		;
 | 
			
		||||
	adc	r22, r1		;
 | 
			
		||||
	adc	r23, r1		;
 | 
			
		||||
	adc	r24, r1		;
 | 
			
		||||
	adc	r25, r1		;/
 | 
			
		||||
0:	sbrs	r18, 7		;When digits indicates zero filled,
 | 
			
		||||
	rjmp	1f		;filler is '0'.
 | 
			
		||||
	neg	r18		;
 | 
			
		||||
	ldi	r19, '0'	;/
 | 
			
		||||
				;----- string conversion loop
 | 
			
		||||
1:	ldi	r21, 32		;r26 = r25:r22 % r20
 | 
			
		||||
	clr	r26		;r25:r22 /= r20
 | 
			
		||||
2:	lsl	r22		;
 | 
			
		||||
	rol	r23		;
 | 
			
		||||
	rol	r24		;
 | 
			
		||||
	rol	r25		;
 | 
			
		||||
	rol	r26		;
 | 
			
		||||
	cp	r26, r20	;
 | 
			
		||||
	brcs	3f		;
 | 
			
		||||
	sub	r26, r20	;
 | 
			
		||||
	inc	r22		;
 | 
			
		||||
3:	dec	r21		;
 | 
			
		||||
	brne	2b		;/
 | 
			
		||||
	cpi	r26, 10		;r26 is a numeral digit '0'-'F'
 | 
			
		||||
	brcs	4f		;
 | 
			
		||||
	subi	r26, -7		;
 | 
			
		||||
4:	subi	r26, -'0'	;/
 | 
			
		||||
	push	r26		;Stack it
 | 
			
		||||
	inc	r31		;/
 | 
			
		||||
	cp	r22, r1		;Repeat until r25:r22 gets zero
 | 
			
		||||
	cpc	r23, r1		;
 | 
			
		||||
	cpc	r24, r1		;
 | 
			
		||||
	cpc	r25, r1		;
 | 
			
		||||
	brne	1b		;/
 | 
			
		||||
 | 
			
		||||
	cpi	r30, '-'	;Minus sign if needed
 | 
			
		||||
	brne	5f		;
 | 
			
		||||
	push	r30		;
 | 
			
		||||
	inc	r31		;/
 | 
			
		||||
5:	cp	r31, r18	;Filler
 | 
			
		||||
	brcc	6f		;
 | 
			
		||||
	push	r19		;
 | 
			
		||||
	inc	r31		;
 | 
			
		||||
	rjmp	5b		;/
 | 
			
		||||
 | 
			
		||||
6:	pop	r24		;Flush stacked digits and exit
 | 
			
		||||
	rcall	xputc		;
 | 
			
		||||
	dec	r31		;
 | 
			
		||||
	brne	6b		;/
 | 
			
		||||
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;---------------------------------------------------------------------------;
 | 
			
		||||
; Formatted string output (16/32bit version)
 | 
			
		||||
;
 | 
			
		||||
;Prototype:
 | 
			
		||||
; void __xprintf (const char *format_p, ...);
 | 
			
		||||
; void __xsprintf(char*, const char *format_p, ...);
 | 
			
		||||
; void __xfprintf(void(*func)(char), const char *format_p, ...);
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
#if USE_XPRINTF
 | 
			
		||||
 | 
			
		||||
.func xvprintf
 | 
			
		||||
xvprintf:
 | 
			
		||||
	ld	ZL, Y+		;Z = pointer to format string
 | 
			
		||||
	ld	ZH, Y+		;/
 | 
			
		||||
 | 
			
		||||
0:	_LPMI	r24		;Get a format char
 | 
			
		||||
	cpi	r24, 0		;End of format string?
 | 
			
		||||
	breq	90f		;/
 | 
			
		||||
	cpi	r24, '%'	;Is format?
 | 
			
		||||
	breq	20f		;/
 | 
			
		||||
1:	rcall	xputc		;Put a normal character
 | 
			
		||||
	rjmp	0b		;/
 | 
			
		||||
90:	ret
 | 
			
		||||
 | 
			
		||||
20:	ldi	r18, 0		;r18: digits
 | 
			
		||||
	clt			;T: filler
 | 
			
		||||
	_LPMI	r21		;Get flags
 | 
			
		||||
	cpi	r21, '%'	;Is a %?
 | 
			
		||||
	breq	1b		;/
 | 
			
		||||
	cpi	r21, '0'	;Zero filled?
 | 
			
		||||
	brne	23f		;
 | 
			
		||||
	set			;/
 | 
			
		||||
22:	_LPMI	r21		;Get width
 | 
			
		||||
23:	cpi	r21, '9'+1	;
 | 
			
		||||
	brcc	24f		;
 | 
			
		||||
	subi	r21, '0'	;
 | 
			
		||||
	brcs	90b		;
 | 
			
		||||
	lsl	r18		;
 | 
			
		||||
	mov	r0, r18		;
 | 
			
		||||
	lsl	r18		;
 | 
			
		||||
	lsl	r18		;
 | 
			
		||||
	add	r18, r0		;
 | 
			
		||||
	add	r18, r21	;
 | 
			
		||||
	rjmp	22b		;/
 | 
			
		||||
 | 
			
		||||
24:	brtc	25f		;get value (low word)
 | 
			
		||||
	neg	r18		;
 | 
			
		||||
25:	ld	r24, Y+		;
 | 
			
		||||
	ld	r25, Y+		;/
 | 
			
		||||
	cpi	r21, 'c'	;Is type character?
 | 
			
		||||
	breq	1b		;/
 | 
			
		||||
	cpi	r21, 's'	;Is type RAM string?
 | 
			
		||||
	breq	50f		;/
 | 
			
		||||
	cpi	r21, 'S'	;Is type ROM string?
 | 
			
		||||
	breq	60f		;/
 | 
			
		||||
	_MOVW	r23,r22,r25,r24	;r25:r22 = value
 | 
			
		||||
	clr	r24		;
 | 
			
		||||
	clr	r25		;
 | 
			
		||||
	clt			;/
 | 
			
		||||
	cpi	r21, 'l'	;Is long int?
 | 
			
		||||
	brne	26f		;
 | 
			
		||||
	ld	r24, Y+		;get value (high word)
 | 
			
		||||
	ld	r25, Y+		;
 | 
			
		||||
	set			;
 | 
			
		||||
	_LPMI	r21		;/
 | 
			
		||||
26:	cpi	r21, 'd'	;Is type signed decimal?
 | 
			
		||||
	brne	27f		;/
 | 
			
		||||
	ldi	r20, -10	;
 | 
			
		||||
	brts	40f		;
 | 
			
		||||
	sbrs	r23, 7		;
 | 
			
		||||
	rjmp	40f		;
 | 
			
		||||
	ldi	r24, -1		;
 | 
			
		||||
	ldi	r25, -1		;
 | 
			
		||||
	rjmp	40f		;/
 | 
			
		||||
27:	cpi	r21, 'u'	;Is type unsigned decimal?
 | 
			
		||||
	ldi	r20, 10		;
 | 
			
		||||
	breq	40f		;/
 | 
			
		||||
	cpi	r21, 'X'	;Is type hexdecimal?
 | 
			
		||||
	ldi	r20, 16		;
 | 
			
		||||
	breq	40f		;/
 | 
			
		||||
	cpi	r21, 'b'	;Is type binary?
 | 
			
		||||
	ldi	r20, 2		;
 | 
			
		||||
	breq	40f		;/
 | 
			
		||||
	ret			;abort
 | 
			
		||||
40:	push	ZH		;Output the value
 | 
			
		||||
	push	ZL		;
 | 
			
		||||
	rcall	xitoa		;
 | 
			
		||||
42:	pop	ZL		;
 | 
			
		||||
	pop	ZH		;
 | 
			
		||||
	rjmp	0b		;/
 | 
			
		||||
 | 
			
		||||
50:	push	ZH		;Put a string on the RAM
 | 
			
		||||
	push	ZL
 | 
			
		||||
	_MOVW	ZH,ZL, r25,r24
 | 
			
		||||
51:	ld	r24, Z+
 | 
			
		||||
	cpi	r24, 0
 | 
			
		||||
	breq	42b
 | 
			
		||||
	rcall	xputc
 | 
			
		||||
	rjmp	51b
 | 
			
		||||
 | 
			
		||||
60:	push	ZH		;Put a string on the ROM
 | 
			
		||||
	push	ZL
 | 
			
		||||
	rcall	xputs
 | 
			
		||||
	rjmp	42b
 | 
			
		||||
.endfunc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.func __xprintf
 | 
			
		||||
.global __xprintf
 | 
			
		||||
__xprintf:
 | 
			
		||||
	push	YH
 | 
			
		||||
	push	YL
 | 
			
		||||
	in	YL, _SFR_IO_ADDR(SPL)
 | 
			
		||||
#ifdef SPH
 | 
			
		||||
	in	YH, _SFR_IO_ADDR(SPH)
 | 
			
		||||
#else
 | 
			
		||||
	clr	YH
 | 
			
		||||
#endif
 | 
			
		||||
	adiw	YL, 5		;Y = pointer to arguments
 | 
			
		||||
	rcall	xvprintf
 | 
			
		||||
	pop	YL
 | 
			
		||||
	pop	YH
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if USE_XSPRINTF
 | 
			
		||||
 | 
			
		||||
.func __xsprintf
 | 
			
		||||
putram:
 | 
			
		||||
	_MOVW	ZH,ZL, r15,r14
 | 
			
		||||
	st	Z+, r24
 | 
			
		||||
	_MOVW	r15,r14, ZH,ZL
 | 
			
		||||
	ret
 | 
			
		||||
.global __xsprintf
 | 
			
		||||
__xsprintf:
 | 
			
		||||
	push	YH
 | 
			
		||||
	push	YL
 | 
			
		||||
	in	YL, _SFR_IO_ADDR(SPL)
 | 
			
		||||
#ifdef SPH
 | 
			
		||||
	in	YH, _SFR_IO_ADDR(SPH)
 | 
			
		||||
#else
 | 
			
		||||
	clr	YH
 | 
			
		||||
#endif
 | 
			
		||||
	adiw	YL, 5		;Y = pointer to arguments
 | 
			
		||||
	lds	ZL, xfunc_out+0	;Save registered output function
 | 
			
		||||
	lds	ZH, xfunc_out+1	;
 | 
			
		||||
	push	ZL		;
 | 
			
		||||
	push	ZH		;/
 | 
			
		||||
	ldi	ZL, lo8(pm(putram));Set local output function
 | 
			
		||||
	ldi	ZH, hi8(pm(putram));
 | 
			
		||||
	sts	xfunc_out+0, ZL	;
 | 
			
		||||
	sts	xfunc_out+1, ZH	;/
 | 
			
		||||
	push	r15		;Initialize pointer to string buffer
 | 
			
		||||
	push	r14		;
 | 
			
		||||
	ld	r14, Y+		;
 | 
			
		||||
	ld	r15, Y+		;/
 | 
			
		||||
	rcall	xvprintf
 | 
			
		||||
	_MOVW	ZH,ZL, r15,r14	;Terminate string
 | 
			
		||||
	st	Z, r1		;
 | 
			
		||||
	pop	r14		;
 | 
			
		||||
	pop	r15		;/
 | 
			
		||||
	pop	ZH		;Restore registered output function
 | 
			
		||||
	pop	ZL		;
 | 
			
		||||
	sts	xfunc_out+0, ZL	;
 | 
			
		||||
	sts	xfunc_out+1, ZH	;/
 | 
			
		||||
	pop	YL
 | 
			
		||||
	pop	YH
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if USE_XFPRINTF
 | 
			
		||||
.func __xfprintf
 | 
			
		||||
.global __xfprintf
 | 
			
		||||
__xfprintf:
 | 
			
		||||
	push	YH
 | 
			
		||||
	push	YL
 | 
			
		||||
	in	YL, _SFR_IO_ADDR(SPL)
 | 
			
		||||
#ifdef SPH
 | 
			
		||||
	in	YH, _SFR_IO_ADDR(SPH)
 | 
			
		||||
#else
 | 
			
		||||
	clr	YH
 | 
			
		||||
#endif
 | 
			
		||||
	adiw	YL, 5		;Y = pointer to arguments
 | 
			
		||||
	lds	ZL, xfunc_out+0	;Save registered output function
 | 
			
		||||
	lds	ZH, xfunc_out+1	;
 | 
			
		||||
	push	ZL		;
 | 
			
		||||
	push	ZH		;/
 | 
			
		||||
	ld	ZL, Y+		;Set output function
 | 
			
		||||
	ld	ZH, Y+		;
 | 
			
		||||
	sts	xfunc_out+0, ZL	;
 | 
			
		||||
	sts	xfunc_out+1, ZH	;/
 | 
			
		||||
	rcall	xvprintf
 | 
			
		||||
	pop	ZH		;Restore registered output function
 | 
			
		||||
	pop	ZL		;
 | 
			
		||||
	sts	xfunc_out+0, ZL	;
 | 
			
		||||
	sts	xfunc_out+1, ZH	;/
 | 
			
		||||
	pop	YL
 | 
			
		||||
	pop	YH
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;---------------------------------------------------------------------------
 | 
			
		||||
; Extended numeral string input
 | 
			
		||||
;
 | 
			
		||||
;Prototype:
 | 
			
		||||
; char xatoi (           /* 1: Successful, 0: Failed */
 | 
			
		||||
;      const char **str, /* pointer to pointer to source string */
 | 
			
		||||
;      long *res         /* result */
 | 
			
		||||
; );
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if USE_XATOI
 | 
			
		||||
.func xatoi
 | 
			
		||||
.global xatoi
 | 
			
		||||
xatoi:
 | 
			
		||||
	_MOVW	r1, r0, r23, r22
 | 
			
		||||
	_MOVW	XH, XL, r25, r24
 | 
			
		||||
	ld	ZL, X+
 | 
			
		||||
	ld	ZH, X+
 | 
			
		||||
	clr	r18		;r21:r18 = 0;
 | 
			
		||||
	clr	r19		;
 | 
			
		||||
	clr	r20		;
 | 
			
		||||
	clr	r21		;/
 | 
			
		||||
	clt			;T = 0;
 | 
			
		||||
 | 
			
		||||
	ldi	r25, 10		;r25 = 10;
 | 
			
		||||
	rjmp	41f		;/
 | 
			
		||||
40:	adiw	ZL, 1		;Z++;
 | 
			
		||||
41:	ld	r22, Z		;r22 = *Z;
 | 
			
		||||
	cpi	r22, ' '	;if(r22 == ' ') continue
 | 
			
		||||
	breq	40b		;/
 | 
			
		||||
	brcs	70f		;if(r22 < ' ') error;
 | 
			
		||||
	cpi	r22, '-'	;if(r22 == '-') {
 | 
			
		||||
	brne	42f		; T = 1;
 | 
			
		||||
	set			; continue;
 | 
			
		||||
	rjmp	40b		;}
 | 
			
		||||
42:	cpi	r22, '9'+1	;if(r22 > '9') error;
 | 
			
		||||
	brcc	70f		;/
 | 
			
		||||
	cpi	r22, '0'	;if(r22 < '0') error;
 | 
			
		||||
	brcs	70f		;/
 | 
			
		||||
	brne	51f		;if(r22 > '0') cv_start;
 | 
			
		||||
	ldi	r25, 8		;r25 = 8;
 | 
			
		||||
	adiw	ZL, 1		;r22 = *(++Z);
 | 
			
		||||
	ld	r22, Z		;/
 | 
			
		||||
	cpi	r22, ' '+1	;if(r22 <= ' ') exit;
 | 
			
		||||
	brcs	80f		;/
 | 
			
		||||
	cpi	r22, 'b'	;if(r22 == 'b') {
 | 
			
		||||
	brne	43f		; r25 = 2;
 | 
			
		||||
	ldi	r25, 2		; cv_start;
 | 
			
		||||
	rjmp	50f		;}
 | 
			
		||||
43:	cpi	r22, 'x'	;if(r22 != 'x') error;
 | 
			
		||||
	brne	51f		;/
 | 
			
		||||
	ldi	r25, 16		;r25 = 16;
 | 
			
		||||
 | 
			
		||||
50:	adiw	ZL, 1		;Z++;
 | 
			
		||||
	ld	r22, Z		;r22 = *Z;
 | 
			
		||||
51:	cpi	r22, ' '+1	;if(r22 <= ' ') break;
 | 
			
		||||
	brcs	80f		;/
 | 
			
		||||
	cpi	r22, 'a'	;if(r22 >= 'a') r22 =- 0x20;
 | 
			
		||||
	brcs	52f		;
 | 
			
		||||
	subi	r22, 0x20	;/
 | 
			
		||||
52:	subi	r22, '0'	;if((r22 -= '0') < 0) error;
 | 
			
		||||
	brcs	70f		;/
 | 
			
		||||
	cpi	r22, 10		;if(r22 >= 10) {
 | 
			
		||||
	brcs	53f		; r22 -= 7;
 | 
			
		||||
	subi	r22, 7		; if(r22 < 10) 
 | 
			
		||||
	cpi	r22, 10		;
 | 
			
		||||
	brcs	70f		;}
 | 
			
		||||
53:	cp	r22, r25	;if(r22 >= r25) error;
 | 
			
		||||
	brcc	70f		;/
 | 
			
		||||
60:	ldi	r24, 33		;r21:r18 *= r25;
 | 
			
		||||
	sub	r23, r23	;
 | 
			
		||||
61:	brcc	62f		;
 | 
			
		||||
	add	r23, r25	;
 | 
			
		||||
62:	lsr	r23		;
 | 
			
		||||
	ror	r21		;
 | 
			
		||||
	ror	r20		;
 | 
			
		||||
	ror	r19		;
 | 
			
		||||
	ror	r18		;
 | 
			
		||||
	dec	r24		;
 | 
			
		||||
	brne	61b		;/
 | 
			
		||||
	add	r18, r22	;r21:r18 += r22;
 | 
			
		||||
	adc	r19, r24	;
 | 
			
		||||
	adc	r20, r24	;
 | 
			
		||||
	adc	r21, r24	;/
 | 
			
		||||
	rjmp	50b		;repeat
 | 
			
		||||
 | 
			
		||||
70:	ldi	r24, 0
 | 
			
		||||
	rjmp	81f
 | 
			
		||||
80:	ldi	r24, 1
 | 
			
		||||
81:	brtc	82f
 | 
			
		||||
	clr	r22
 | 
			
		||||
	com	r18
 | 
			
		||||
	com	r19
 | 
			
		||||
	com	r20
 | 
			
		||||
	com	r21
 | 
			
		||||
	adc	r18, r22
 | 
			
		||||
	adc	r19, r22
 | 
			
		||||
	adc	r20, r22
 | 
			
		||||
	adc	r21, r22
 | 
			
		||||
82:	st	-X, ZH
 | 
			
		||||
	st	-X, ZL
 | 
			
		||||
	_MOVW	XH, XL, r1, r0
 | 
			
		||||
	st	X+, r18
 | 
			
		||||
	st	X+, r19
 | 
			
		||||
	st	X+, r20
 | 
			
		||||
	st	X+, r21
 | 
			
		||||
	clr	r1
 | 
			
		||||
	ret
 | 
			
		||||
.endfunc
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										111
									
								
								common/avr/xprintf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								common/avr/xprintf.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
/*---------------------------------------------------------------------------
 | 
			
		||||
   Extended itoa, puts and printf                    (C)ChaN, 2011
 | 
			
		||||
-----------------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#ifndef XPRINTF_H
 | 
			
		||||
#define XPRINTF_H
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <avr/pgmspace.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern void (*xfunc_out)(uint8_t);
 | 
			
		||||
#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
 | 
			
		||||
 | 
			
		||||
/* This is a pointer to user defined output function. It must be initialized
 | 
			
		||||
   before using this modle.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void xputc(char chr);
 | 
			
		||||
 | 
			
		||||
/* This is a stub function to forward outputs to user defined output function.
 | 
			
		||||
   All outputs from this module are output via this function.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------------*/
 | 
			
		||||
void xputs(const char *string_p);
 | 
			
		||||
 | 
			
		||||
/*  The string placed in the ROM is forwarded to xputc() directly.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------------*/
 | 
			
		||||
void xitoa(long value, char radix, char width);
 | 
			
		||||
 | 
			
		||||
/* Extended itoa().
 | 
			
		||||
 | 
			
		||||
      value  radix  width   output
 | 
			
		||||
        100     10      6   "   100"
 | 
			
		||||
        100     10     -6   "000100"
 | 
			
		||||
        100     10      0   "100"
 | 
			
		||||
 4294967295     10      0   "4294967295"
 | 
			
		||||
 4294967295    -10      0   "-1"
 | 
			
		||||
     655360     16     -8   "000A0000"
 | 
			
		||||
       1024     16      0   "400"
 | 
			
		||||
       0x55      2     -8   "01010101"
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------------*/
 | 
			
		||||
#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)
 | 
			
		||||
#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)
 | 
			
		||||
#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
void __xprintf(const char *format_p, ...);	/* Send formatted string to the registered device */
 | 
			
		||||
void __xsprintf(char*, const char *format_p, ...);	/* Put formatted string to the memory */
 | 
			
		||||
void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */
 | 
			
		||||
 | 
			
		||||
/* Format string is placed in the ROM. The format flags is similar to printf().
 | 
			
		||||
 | 
			
		||||
   %[flag][width][size]type
 | 
			
		||||
 | 
			
		||||
   flag
 | 
			
		||||
     A '0' means filled with '0' when output is shorter than width.
 | 
			
		||||
     ' ' is used in default. This is effective only numeral type.
 | 
			
		||||
   width
 | 
			
		||||
     Minimum width in decimal number. This is effective only numeral type.
 | 
			
		||||
     Default width is zero.
 | 
			
		||||
   size
 | 
			
		||||
     A 'l' means the argument is long(32bit). Default is short(16bit).
 | 
			
		||||
     This is effective only numeral type.
 | 
			
		||||
   type
 | 
			
		||||
     'c' : Character, argument is the value
 | 
			
		||||
     's' : String placed on the RAM, argument is the pointer
 | 
			
		||||
     'S' : String placed on the ROM, argument is the pointer
 | 
			
		||||
     'd' : Signed decimal, argument is the value
 | 
			
		||||
     'u' : Unsigned decimal, argument is the value
 | 
			
		||||
     'X' : Hexdecimal, argument is the value
 | 
			
		||||
     'b' : Binary, argument is the value
 | 
			
		||||
     '%' : '%'
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------------*/
 | 
			
		||||
char xatoi(char **str, long *ret);
 | 
			
		||||
 | 
			
		||||
/* Get value of the numeral string. 
 | 
			
		||||
 | 
			
		||||
  str
 | 
			
		||||
    Pointer to pointer to source string
 | 
			
		||||
 | 
			
		||||
    "0b11001010" binary
 | 
			
		||||
    "0377" octal
 | 
			
		||||
    "0xff800" hexdecimal
 | 
			
		||||
    "1250000" decimal
 | 
			
		||||
    "-25000" decimal
 | 
			
		||||
 | 
			
		||||
  ret
 | 
			
		||||
    Pointer to return value
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								common/backlight.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								common/backlight.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Mathias Andersson <wraul@dbox.se>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "backlight.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
backlight_config_t backlight_config;
 | 
			
		||||
 | 
			
		||||
void backlight_init(void)
 | 
			
		||||
{
 | 
			
		||||
    /* check signature */
 | 
			
		||||
    if (!eeconfig_is_enabled()) {
 | 
			
		||||
        eeconfig_init();
 | 
			
		||||
    }
 | 
			
		||||
    backlight_config.raw = eeconfig_read_backlight();
 | 
			
		||||
    backlight_set(backlight_config.enable ? backlight_config.level : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backlight_increase(void)
 | 
			
		||||
{
 | 
			
		||||
    if(backlight_config.level < BACKLIGHT_LEVELS)
 | 
			
		||||
    {
 | 
			
		||||
        backlight_config.level++;
 | 
			
		||||
        backlight_config.enable = 1;
 | 
			
		||||
        eeconfig_write_backlight(backlight_config.raw);
 | 
			
		||||
    }
 | 
			
		||||
    dprintf("backlight increase: %u\n", backlight_config.level);
 | 
			
		||||
    backlight_set(backlight_config.level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backlight_decrease(void)
 | 
			
		||||
{
 | 
			
		||||
    if(backlight_config.level > 0)
 | 
			
		||||
    {
 | 
			
		||||
        backlight_config.level--;
 | 
			
		||||
        backlight_config.enable = !!backlight_config.level;
 | 
			
		||||
        eeconfig_write_backlight(backlight_config.raw);
 | 
			
		||||
    }
 | 
			
		||||
    dprintf("backlight decrease: %u\n", backlight_config.level);
 | 
			
		||||
    backlight_set(backlight_config.level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backlight_toggle(void)
 | 
			
		||||
{
 | 
			
		||||
    backlight_config.enable ^= 1;
 | 
			
		||||
    eeconfig_write_backlight(backlight_config.raw);
 | 
			
		||||
    dprintf("backlight toggle: %u\n", backlight_config.enable);
 | 
			
		||||
    backlight_set(backlight_config.enable ? backlight_config.level : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backlight_step(void)
 | 
			
		||||
{
 | 
			
		||||
    backlight_config.level++;
 | 
			
		||||
    if(backlight_config.level > BACKLIGHT_LEVELS)
 | 
			
		||||
    {
 | 
			
		||||
        backlight_config.level = 0;
 | 
			
		||||
    }
 | 
			
		||||
    backlight_config.enable = !!backlight_config.level;
 | 
			
		||||
    eeconfig_write_backlight(backlight_config.raw);
 | 
			
		||||
    dprintf("backlight step: %u\n", backlight_config.level);
 | 
			
		||||
    backlight_set(backlight_config.level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backlight_level(uint8_t level)
 | 
			
		||||
{
 | 
			
		||||
    backlight_config.level ^= level;
 | 
			
		||||
    backlight_config.enable = !!backlight_config.level;
 | 
			
		||||
    eeconfig_write_backlight(backlight_config.raw);
 | 
			
		||||
    backlight_set(backlight_config.level);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								common/backlight.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								common/backlight.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Mathias Andersson <wraul@dbox.se>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BACKLIGHT_H
 | 
			
		||||
#define BACKLIGHT_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint8_t raw;
 | 
			
		||||
    struct {
 | 
			
		||||
        bool    enable :1;
 | 
			
		||||
        uint8_t level  :7;
 | 
			
		||||
    };
 | 
			
		||||
} backlight_config_t;
 | 
			
		||||
 | 
			
		||||
void backlight_init(void);
 | 
			
		||||
void backlight_increase(void);
 | 
			
		||||
void backlight_decrease(void);
 | 
			
		||||
void backlight_toggle(void);
 | 
			
		||||
void backlight_step(void);
 | 
			
		||||
void backlight_set(uint8_t level);
 | 
			
		||||
void backlight_level(uint8_t level);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										25
									
								
								common/bootloader.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								common/bootloader.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BOOTLOADER_H
 | 
			
		||||
#define BOOTLOADER_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* give code for your bootloader to come up if needed */
 | 
			
		||||
void bootloader_jump(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										128
									
								
								common/bootmagic.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								common/bootmagic.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,128 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "bootmagic.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void bootmagic(void)
 | 
			
		||||
{
 | 
			
		||||
    /* check signature */
 | 
			
		||||
    if (!eeconfig_is_enabled()) {
 | 
			
		||||
        eeconfig_init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* do scans in case of bounce */
 | 
			
		||||
    print("boogmagic scan: ... ");
 | 
			
		||||
    uint8_t scan = 100;
 | 
			
		||||
    while (scan--) { matrix_scan(); _delay_ms(10); }
 | 
			
		||||
    print("done.\n");
 | 
			
		||||
 | 
			
		||||
    /* bootmagic skip */
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* eeconfig clear */
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
 | 
			
		||||
        eeconfig_init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* bootloader */
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
 | 
			
		||||
        bootloader_jump();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* debug enable */
 | 
			
		||||
    debug_config.raw = eeconfig_read_debug();
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
 | 
			
		||||
        if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
 | 
			
		||||
            debug_config.matrix = !debug_config.matrix;
 | 
			
		||||
        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
 | 
			
		||||
            debug_config.keyboard = !debug_config.keyboard;
 | 
			
		||||
        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
 | 
			
		||||
            debug_config.mouse = !debug_config.mouse;
 | 
			
		||||
        } else {
 | 
			
		||||
            debug_config.enable = !debug_config.enable;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    eeconfig_write_debug(debug_config.raw);
 | 
			
		||||
 | 
			
		||||
    /* keymap config */
 | 
			
		||||
    keymap_config.raw = eeconfig_read_keymap();
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
 | 
			
		||||
        keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
 | 
			
		||||
        keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
 | 
			
		||||
        keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
 | 
			
		||||
        keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
 | 
			
		||||
        keymap_config.no_gui = !keymap_config.no_gui;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
 | 
			
		||||
        keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
 | 
			
		||||
        keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
 | 
			
		||||
    }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
 | 
			
		||||
        keymap_config.nkro = !keymap_config.nkro;
 | 
			
		||||
    }
 | 
			
		||||
    eeconfig_write_keymap(keymap_config.raw);
 | 
			
		||||
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    keyboard_nkro = keymap_config.nkro;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* default layer */
 | 
			
		||||
    uint8_t default_layer = 0;
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
 | 
			
		||||
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
 | 
			
		||||
    if (default_layer) {
 | 
			
		||||
        eeconfig_write_default_layer(default_layer);
 | 
			
		||||
        default_layer_set((uint32_t)default_layer);
 | 
			
		||||
    } else {
 | 
			
		||||
        default_layer = eeconfig_read_default_layer();
 | 
			
		||||
        default_layer_set((uint32_t)default_layer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool scan_keycode(uint8_t keycode)
 | 
			
		||||
{
 | 
			
		||||
    for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
 | 
			
		||||
        matrix_row_t matrix_row = matrix_get_row(r);
 | 
			
		||||
        for (uint8_t c = 0; c < MATRIX_COLS; c++) {
 | 
			
		||||
            if (matrix_row & ((matrix_row_t)1<<c)) {
 | 
			
		||||
                if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bootmagic_scan_keycode(uint8_t keycode)
 | 
			
		||||
{
 | 
			
		||||
    if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
 | 
			
		||||
 | 
			
		||||
    return scan_keycode(keycode);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								common/bootmagic.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								common/bootmagic.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,100 @@
 | 
			
		|||
#ifndef BOOTMAGIC_H
 | 
			
		||||
#define BOOTMAGIC_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* bootmagic salt key */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SALT
 | 
			
		||||
#define BOOTMAGIC_KEY_SALT              KC_SPACE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* skip bootmagic and eeconfig */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SKIP
 | 
			
		||||
#define BOOTMAGIC_KEY_SKIP              KC_ESC
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* eeprom clear */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR
 | 
			
		||||
#define BOOTMAGIC_KEY_EEPROM_CLEAR      KC_BSPACE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* kick up bootloader */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_BOOTLOADER
 | 
			
		||||
#define BOOTMAGIC_KEY_BOOTLOADER        KC_B
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* debug enable */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE
 | 
			
		||||
#define BOOTMAGIC_KEY_DEBUG_ENABLE      KC_D
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX
 | 
			
		||||
#define BOOTMAGIC_KEY_DEBUG_MATRIX      KC_X
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD
 | 
			
		||||
#define BOOTMAGIC_KEY_DEBUG_KEYBOARD    KC_K
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE
 | 
			
		||||
#define BOOTMAGIC_KEY_DEBUG_MOUSE       KC_M
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * keymap config
 | 
			
		||||
 */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK
 | 
			
		||||
#define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK     KC_LCTRL
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL
 | 
			
		||||
#define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL       KC_CAPSLOCK
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI
 | 
			
		||||
#define BOOTMAGIC_KEY_SWAP_LALT_LGUI            KC_LALT
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI
 | 
			
		||||
#define BOOTMAGIC_KEY_SWAP_RALT_RGUI            KC_RALT
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_NO_GUI
 | 
			
		||||
#define BOOTMAGIC_KEY_NO_GUI                    KC_LGUI
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC
 | 
			
		||||
#define BOOTMAGIC_KEY_SWAP_GRAVE_ESC            KC_GRAVE
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE
 | 
			
		||||
#define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE  KC_BSLASH
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_HOST_NKRO
 | 
			
		||||
#define BOOTMAGIC_HOST_NKRO              KC_N
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * change default layer
 | 
			
		||||
 */
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_0   KC_0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_1   KC_1
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_2   KC_2
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_3   KC_3
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_4   KC_4
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_5   KC_5
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_6   KC_6
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7
 | 
			
		||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_7   KC_7
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void bootmagic(void);
 | 
			
		||||
bool bootmagic_scan_keycode(uint8_t keycode);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										644
									
								
								common/command.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										644
									
								
								common/command.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,644 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "sleep_led.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "backlight.h"
 | 
			
		||||
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
#include "mousekey.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
#   include "usb_keyboard.h"
 | 
			
		||||
#   ifdef EXTRAKEY_ENABLE
 | 
			
		||||
#       include "usb_extra.h"
 | 
			
		||||
#   endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_VUSB
 | 
			
		||||
#   include "usbdrv.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool command_common(uint8_t code);
 | 
			
		||||
static void command_common_help(void);
 | 
			
		||||
static bool command_console(uint8_t code);
 | 
			
		||||
static void command_console_help(void);
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
static bool mousekey_console(uint8_t code);
 | 
			
		||||
static void mousekey_console_help(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint8_t numkey2num(uint8_t code);
 | 
			
		||||
static void switch_default_layer(uint8_t layer);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
command_state_t command_state = ONESHOT;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool command_proc(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    switch (command_state) {
 | 
			
		||||
        case ONESHOT:
 | 
			
		||||
            if (!IS_COMMAND())
 | 
			
		||||
                return false;
 | 
			
		||||
            return (command_extra(code) || command_common(code));
 | 
			
		||||
            break;
 | 
			
		||||
        case CONSOLE:
 | 
			
		||||
            if (IS_COMMAND())
 | 
			
		||||
                return (command_extra(code) || command_common(code));
 | 
			
		||||
            else
 | 
			
		||||
                return (command_console_extra(code) || command_console(code));
 | 
			
		||||
            break;
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
        case MOUSEKEY:
 | 
			
		||||
            mousekey_console(code);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            command_state = ONESHOT;
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TODO: Refactoring is needed. */
 | 
			
		||||
/* This allows to define extra commands. return false when not processed. */
 | 
			
		||||
bool command_extra(uint8_t code) __attribute__ ((weak));
 | 
			
		||||
bool command_extra(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool command_console_extra(uint8_t code) __attribute__ ((weak));
 | 
			
		||||
bool command_console_extra(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************************
 | 
			
		||||
 * Command common
 | 
			
		||||
 ***********************************************************/
 | 
			
		||||
static void command_common_help(void)
 | 
			
		||||
{
 | 
			
		||||
    print("\n\n----- Command Help -----\n");
 | 
			
		||||
    print("c:	enter console mode\n");
 | 
			
		||||
    print("d:	toggle debug enable\n");
 | 
			
		||||
    print("x:	toggle matrix debug\n");
 | 
			
		||||
    print("k:	toggle keyboard debug\n");
 | 
			
		||||
    print("m:	toggle mouse debug\n");
 | 
			
		||||
#ifdef SLEEP_LED_ENABLE
 | 
			
		||||
    print("z:	toggle sleep LED test\n");
 | 
			
		||||
#endif
 | 
			
		||||
    print("v:	print device version & info\n");
 | 
			
		||||
    print("t:	print timer count\n");
 | 
			
		||||
    print("s:	print status\n");
 | 
			
		||||
    print("e:	print eeprom config\n");
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    print("n:	toggle NKRO\n");
 | 
			
		||||
#endif
 | 
			
		||||
    print("0/F10:	switch to Layer0 \n");
 | 
			
		||||
    print("1/F1:	switch to Layer1 \n");
 | 
			
		||||
    print("2/F2:	switch to Layer2 \n");
 | 
			
		||||
    print("3/F3:	switch to Layer3 \n");
 | 
			
		||||
    print("4/F4:	switch to Layer4 \n");
 | 
			
		||||
    print("PScr:	power down/remote wake-up\n");
 | 
			
		||||
    print("Caps:	Lock Keyboard(Child Proof)\n");
 | 
			
		||||
    print("Paus:	jump to bootloader\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
static void print_eeconfig(void)
 | 
			
		||||
{
 | 
			
		||||
    print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
 | 
			
		||||
 | 
			
		||||
    debug_config_t dc;
 | 
			
		||||
    dc.raw = eeconfig_read_debug();
 | 
			
		||||
    print("debug_config.raw: "); print_hex8(dc.raw); print("\n");
 | 
			
		||||
    print(".enable: "); print_dec(dc.enable); print("\n");
 | 
			
		||||
    print(".matrix: "); print_dec(dc.matrix); print("\n");
 | 
			
		||||
    print(".keyboard: "); print_dec(dc.keyboard); print("\n");
 | 
			
		||||
    print(".mouse: "); print_dec(dc.mouse); print("\n");
 | 
			
		||||
 | 
			
		||||
    keymap_config_t kc;
 | 
			
		||||
    kc.raw = eeconfig_read_keymap();
 | 
			
		||||
    print("keymap_config.raw: "); print_hex8(kc.raw); print("\n");
 | 
			
		||||
    print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n");
 | 
			
		||||
    print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n");
 | 
			
		||||
    print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n");
 | 
			
		||||
    print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n");
 | 
			
		||||
    print(".no_gui: "); print_dec(kc.no_gui); print("\n");
 | 
			
		||||
    print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n");
 | 
			
		||||
    print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n");
 | 
			
		||||
    print(".nkro: "); print_dec(kc.nkro); print("\n");
 | 
			
		||||
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
    backlight_config_t bc;
 | 
			
		||||
    bc.raw = eeconfig_read_backlight();
 | 
			
		||||
    print("backlight_config.raw: "); print_hex8(bc.raw); print("\n");
 | 
			
		||||
    print(".enable: "); print_dec(bc.enable); print("\n");
 | 
			
		||||
    print(".level: "); print_dec(bc.level); print("\n");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool command_common(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    static host_driver_t *host_driver = 0;
 | 
			
		||||
    switch (code) {
 | 
			
		||||
#ifdef SLEEP_LED_ENABLE
 | 
			
		||||
        case KC_Z:
 | 
			
		||||
            // test breathing sleep LED
 | 
			
		||||
            print("Sleep LED test\n");
 | 
			
		||||
            sleep_led_toggle();
 | 
			
		||||
            led_set(host_keyboard_leds());
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
        case KC_E:
 | 
			
		||||
            print("eeconfig:\n");
 | 
			
		||||
            print_eeconfig();
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        case KC_CAPSLOCK:
 | 
			
		||||
            if (host_get_driver()) {
 | 
			
		||||
                host_driver = host_get_driver();
 | 
			
		||||
                clear_keyboard();
 | 
			
		||||
                host_set_driver(0);
 | 
			
		||||
                print("Locked.\n");
 | 
			
		||||
            } else {
 | 
			
		||||
                host_set_driver(host_driver);
 | 
			
		||||
                print("Unlocked.\n");
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_H:
 | 
			
		||||
        case KC_SLASH: /* ? */
 | 
			
		||||
            command_common_help();
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_C:
 | 
			
		||||
            debug_matrix   = false;
 | 
			
		||||
            debug_keyboard = false;
 | 
			
		||||
            debug_mouse    = false;
 | 
			
		||||
            debug_enable   = false;
 | 
			
		||||
            command_console_help();
 | 
			
		||||
            print("\nEnter Console Mode\n");
 | 
			
		||||
            print("C> ");
 | 
			
		||||
            command_state = CONSOLE;
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_PAUSE:
 | 
			
		||||
            clear_keyboard();
 | 
			
		||||
            print("\n\nJump to bootloader... ");
 | 
			
		||||
            _delay_ms(1000);
 | 
			
		||||
            bootloader_jump(); // not return
 | 
			
		||||
            print("not supported.\n");
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_D:
 | 
			
		||||
            if (debug_enable) {
 | 
			
		||||
                print("\nDEBUG: disabled.\n");
 | 
			
		||||
                debug_matrix   = false;
 | 
			
		||||
                debug_keyboard = false;
 | 
			
		||||
                debug_mouse    = false;
 | 
			
		||||
                debug_enable   = false;
 | 
			
		||||
            } else {
 | 
			
		||||
                print("\nDEBUG: enabled.\n");
 | 
			
		||||
                debug_enable   = true;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_X: // debug matrix toggle
 | 
			
		||||
            debug_matrix = !debug_matrix;
 | 
			
		||||
            if (debug_matrix) {
 | 
			
		||||
                print("\nDEBUG: matrix enabled.\n");
 | 
			
		||||
                debug_enable = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                print("\nDEBUG: matrix disabled.\n");
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_K: // debug keyboard toggle
 | 
			
		||||
            debug_keyboard = !debug_keyboard;
 | 
			
		||||
            if (debug_keyboard) {
 | 
			
		||||
                print("\nDEBUG: keyboard enabled.\n");
 | 
			
		||||
                debug_enable = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                print("\nDEBUG: keyboard disabled.\n");
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_M: // debug mouse toggle
 | 
			
		||||
            debug_mouse = !debug_mouse;
 | 
			
		||||
            if (debug_mouse) {
 | 
			
		||||
                print("\nDEBUG: mouse enabled.\n");
 | 
			
		||||
                debug_enable = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                print("\nDEBUG: mouse disabled.\n");
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_V: // print version & information
 | 
			
		||||
            print("\n\n----- Version -----\n");
 | 
			
		||||
            print("DESC: " STR(DESCRIPTION) "\n");
 | 
			
		||||
            print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
 | 
			
		||||
                  "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
 | 
			
		||||
                  "VER: " STR(DEVICE_VER) "\n");
 | 
			
		||||
            print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
 | 
			
		||||
            /* build options */
 | 
			
		||||
            print("OPTIONS:"
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
            " PJRC"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
            " LUFA"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef PROTOCOL_VUSB
 | 
			
		||||
            " VUSB"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
            " BOOTMAGIC"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
            " MOUSEKEY"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
            " EXTRAKEY"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONSOLE_ENABLE
 | 
			
		||||
            " CONSOLE"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef COMMAND_ENABLE
 | 
			
		||||
            " COMMAND"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
            " NKRO"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef KEYMAP_SECTION_ENABLE
 | 
			
		||||
            " KEYMAP_SECTION"
 | 
			
		||||
#endif
 | 
			
		||||
            " " STR(BOOTLOADER_SIZE) "\n");
 | 
			
		||||
 | 
			
		||||
            print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
 | 
			
		||||
                  " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
 | 
			
		||||
                  " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_T: // print timer
 | 
			
		||||
            print_val_hex32(timer_count);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_S:
 | 
			
		||||
            print("\n\n----- Status -----\n");
 | 
			
		||||
            print_val_hex8(host_keyboard_leds());
 | 
			
		||||
            print_val_hex8(keyboard_protocol);
 | 
			
		||||
            print_val_hex8(keyboard_idle);
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
            print_val_hex8(UDCON);
 | 
			
		||||
            print_val_hex8(UDIEN);
 | 
			
		||||
            print_val_hex8(UDINT);
 | 
			
		||||
            print_val_hex8(usb_keyboard_leds);
 | 
			
		||||
            print_val_hex8(usb_keyboard_idle_count);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
#   if USB_COUNT_SOF
 | 
			
		||||
            print_val_hex8(usbSofCount);
 | 
			
		||||
#   endif
 | 
			
		||||
#endif
 | 
			
		||||
            break;
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
        case KC_N:
 | 
			
		||||
            clear_keyboard(); //Prevents stuck keys.
 | 
			
		||||
            keyboard_nkro = !keyboard_nkro;
 | 
			
		||||
            if (keyboard_nkro)
 | 
			
		||||
                print("NKRO: enabled\n");
 | 
			
		||||
            else
 | 
			
		||||
                print("NKRO: disabled\n");
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
        case KC_PSCREEN:
 | 
			
		||||
            // TODO: Power key should take this feature? otherwise any key during suspend.
 | 
			
		||||
#ifdef PROTOCOL_PJRC
 | 
			
		||||
            if (suspend && remote_wakeup) {
 | 
			
		||||
                usb_remote_wakeup();
 | 
			
		||||
            } else {
 | 
			
		||||
                host_system_send(SYSTEM_POWER_DOWN);
 | 
			
		||||
                host_system_send(0);
 | 
			
		||||
                _delay_ms(500);
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
            host_system_send(SYSTEM_POWER_DOWN);
 | 
			
		||||
            _delay_ms(100);
 | 
			
		||||
            host_system_send(0);
 | 
			
		||||
            _delay_ms(500);
 | 
			
		||||
#endif
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        case KC_ESC:
 | 
			
		||||
        case KC_GRV:
 | 
			
		||||
        case KC_0:
 | 
			
		||||
            switch_default_layer(0);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_1 ... KC_9:
 | 
			
		||||
            switch_default_layer((code - KC_1) + 1);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_F1 ... KC_F12:
 | 
			
		||||
            switch_default_layer((code - KC_F1) + 1);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            print("?");
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************************
 | 
			
		||||
 * Command console
 | 
			
		||||
 ***********************************************************/
 | 
			
		||||
static void command_console_help(void)
 | 
			
		||||
{
 | 
			
		||||
    print("\n\n----- Console Help -----\n");
 | 
			
		||||
    print("ESC/q:	quit\n");
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    print("m:	mousekey\n");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool command_console(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    switch (code) {
 | 
			
		||||
        case KC_H:
 | 
			
		||||
        case KC_SLASH: /* ? */
 | 
			
		||||
            command_console_help();
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_Q:
 | 
			
		||||
        case KC_ESC:
 | 
			
		||||
            print("\nQuit Console Mode\n");
 | 
			
		||||
            command_state = ONESHOT;
 | 
			
		||||
            return false;
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
        case KC_M:
 | 
			
		||||
            mousekey_console_help();
 | 
			
		||||
            print("\nEnter Mousekey Console\n");
 | 
			
		||||
            print("M0>");
 | 
			
		||||
            command_state = MOUSEKEY;
 | 
			
		||||
            return true;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            print("?");
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    print("C> ");
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
/***********************************************************
 | 
			
		||||
 * Mousekey console
 | 
			
		||||
 ***********************************************************/
 | 
			
		||||
static uint8_t mousekey_param = 0;
 | 
			
		||||
 | 
			
		||||
static void mousekey_param_print(void)
 | 
			
		||||
{
 | 
			
		||||
    print("\n\n----- Mousekey Parameters -----\n");
 | 
			
		||||
    print("1: mk_delay(*10ms): "); pdec(mk_delay); print("\n");
 | 
			
		||||
    print("2: mk_interval(ms): "); pdec(mk_interval); print("\n");
 | 
			
		||||
    print("3: mk_max_speed: "); pdec(mk_max_speed); print("\n");
 | 
			
		||||
    print("4: mk_time_to_max: "); pdec(mk_time_to_max); print("\n");
 | 
			
		||||
    print("5: mk_wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
 | 
			
		||||
    print("6: mk_wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PRINT_SET_VAL(v)  print(#v " = "); print_dec(v); print("\n");
 | 
			
		||||
static void mousekey_param_inc(uint8_t param, uint8_t inc)
 | 
			
		||||
{
 | 
			
		||||
    switch (param) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            if (mk_delay + inc < UINT8_MAX)
 | 
			
		||||
                mk_delay += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_delay = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_delay);
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            if (mk_interval + inc < UINT8_MAX)
 | 
			
		||||
                mk_interval += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_interval = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_interval);
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            if (mk_max_speed + inc < UINT8_MAX)
 | 
			
		||||
                mk_max_speed += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_max_speed = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_max_speed);
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            if (mk_time_to_max + inc < UINT8_MAX)
 | 
			
		||||
                mk_time_to_max += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_time_to_max = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_time_to_max);
 | 
			
		||||
            break;
 | 
			
		||||
        case 5:
 | 
			
		||||
            if (mk_wheel_max_speed + inc < UINT8_MAX)
 | 
			
		||||
                mk_wheel_max_speed += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_wheel_max_speed = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_wheel_max_speed);
 | 
			
		||||
            break;
 | 
			
		||||
        case 6:
 | 
			
		||||
            if (mk_wheel_time_to_max + inc < UINT8_MAX)
 | 
			
		||||
                mk_wheel_time_to_max += inc;
 | 
			
		||||
            else
 | 
			
		||||
                mk_wheel_time_to_max = UINT8_MAX;
 | 
			
		||||
            PRINT_SET_VAL(mk_wheel_time_to_max);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mousekey_param_dec(uint8_t param, uint8_t dec)
 | 
			
		||||
{
 | 
			
		||||
    switch (param) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            if (mk_delay > dec)
 | 
			
		||||
                mk_delay -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_delay = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_delay);
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            if (mk_interval > dec)
 | 
			
		||||
                mk_interval -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_interval = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_interval);
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            if (mk_max_speed > dec)
 | 
			
		||||
                mk_max_speed -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_max_speed = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_max_speed);
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            if (mk_time_to_max > dec)
 | 
			
		||||
                mk_time_to_max -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_time_to_max = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_time_to_max);
 | 
			
		||||
            break;
 | 
			
		||||
        case 5:
 | 
			
		||||
            if (mk_wheel_max_speed > dec)
 | 
			
		||||
                mk_wheel_max_speed -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_wheel_max_speed = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_wheel_max_speed);
 | 
			
		||||
            break;
 | 
			
		||||
        case 6:
 | 
			
		||||
            if (mk_wheel_time_to_max > dec)
 | 
			
		||||
                mk_wheel_time_to_max -= dec;
 | 
			
		||||
            else
 | 
			
		||||
                mk_wheel_time_to_max = 0;
 | 
			
		||||
            PRINT_SET_VAL(mk_wheel_time_to_max);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mousekey_console_help(void)
 | 
			
		||||
{
 | 
			
		||||
    print("\n\n----- Mousekey Parameters Help -----\n");
 | 
			
		||||
    print("ESC/q:	quit\n");
 | 
			
		||||
    print("1:	select mk_delay(*10ms)\n");
 | 
			
		||||
    print("2:	select mk_interval(ms)\n");
 | 
			
		||||
    print("3:	select mk_max_speed\n");
 | 
			
		||||
    print("4:	select mk_time_to_max\n");
 | 
			
		||||
    print("5:	select mk_wheel_max_speed\n");
 | 
			
		||||
    print("6:	select mk_wheel_time_to_max\n");
 | 
			
		||||
    print("p:	print parameters\n");
 | 
			
		||||
    print("d:	set default values\n");
 | 
			
		||||
    print("up:	increase parameters(+1)\n");
 | 
			
		||||
    print("down:	decrease parameters(-1)\n");
 | 
			
		||||
    print("pgup:	increase parameters(+10)\n");
 | 
			
		||||
    print("pgdown:	decrease parameters(-10)\n");
 | 
			
		||||
    print("\nspeed = delta * max_speed * (repeat / time_to_max)\n");
 | 
			
		||||
    print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA);
 | 
			
		||||
    print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n");
 | 
			
		||||
    print("See http://en.wikipedia.org/wiki/Mouse_keys\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool mousekey_console(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    switch (code) {
 | 
			
		||||
        case KC_H:
 | 
			
		||||
        case KC_SLASH: /* ? */
 | 
			
		||||
            mousekey_console_help();
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_Q:
 | 
			
		||||
        case KC_ESC:
 | 
			
		||||
            mousekey_param = 0;
 | 
			
		||||
            print("\nQuit Mousekey Console\n");
 | 
			
		||||
            print("C> ");
 | 
			
		||||
            command_state = CONSOLE;
 | 
			
		||||
            return false;
 | 
			
		||||
        case KC_P:
 | 
			
		||||
            mousekey_param_print();
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_1:
 | 
			
		||||
        case KC_2:
 | 
			
		||||
        case KC_3:
 | 
			
		||||
        case KC_4:
 | 
			
		||||
        case KC_5:
 | 
			
		||||
        case KC_6:
 | 
			
		||||
        case KC_7:
 | 
			
		||||
        case KC_8:
 | 
			
		||||
        case KC_9:
 | 
			
		||||
        case KC_0:
 | 
			
		||||
            mousekey_param = numkey2num(code);
 | 
			
		||||
            print("selected parameter: "); pdec(mousekey_param); print("\n");
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_UP:
 | 
			
		||||
            mousekey_param_inc(mousekey_param, 1);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_DOWN:
 | 
			
		||||
            mousekey_param_dec(mousekey_param, 1);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_PGUP:
 | 
			
		||||
            mousekey_param_inc(mousekey_param, 10);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_PGDN:
 | 
			
		||||
            mousekey_param_dec(mousekey_param, 10);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_D:
 | 
			
		||||
            mk_delay = MOUSEKEY_DELAY/10;
 | 
			
		||||
            mk_interval = MOUSEKEY_INTERVAL;
 | 
			
		||||
            mk_max_speed = MOUSEKEY_MAX_SPEED;
 | 
			
		||||
            mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
 | 
			
		||||
            mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
 | 
			
		||||
            mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
 | 
			
		||||
            print("set default values.\n");
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            print("?");
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    print("M"); pdec(mousekey_param); print("> ");
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************************
 | 
			
		||||
 * Utilities
 | 
			
		||||
 ***********************************************************/
 | 
			
		||||
static uint8_t numkey2num(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    switch (code) {
 | 
			
		||||
        case KC_1: return 1;
 | 
			
		||||
        case KC_2: return 2;
 | 
			
		||||
        case KC_3: return 3;
 | 
			
		||||
        case KC_4: return 4;
 | 
			
		||||
        case KC_5: return 5;
 | 
			
		||||
        case KC_6: return 6;
 | 
			
		||||
        case KC_7: return 7;
 | 
			
		||||
        case KC_8: return 8;
 | 
			
		||||
        case KC_9: return 9;
 | 
			
		||||
        case KC_0: return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void switch_default_layer(uint8_t layer)
 | 
			
		||||
{
 | 
			
		||||
    print("switch_default_layer: "); print_dec(biton32(default_layer_state));
 | 
			
		||||
    print(" to "); print_dec(layer); print("\n");
 | 
			
		||||
    default_layer_set(1UL<<layer);
 | 
			
		||||
    clear_keyboard();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								common/command.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								common/command.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef COMMAND_H
 | 
			
		||||
#define COMMAND
 | 
			
		||||
 | 
			
		||||
/* TODO: Refactoring */
 | 
			
		||||
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t;
 | 
			
		||||
extern command_state_t command_state;
 | 
			
		||||
 | 
			
		||||
/* This allows to extend commands. Return false when command is not processed. */
 | 
			
		||||
bool command_extra(uint8_t code);
 | 
			
		||||
bool command_console_extra(uint8_t code);
 | 
			
		||||
 | 
			
		||||
#ifdef COMMAND_ENABLE
 | 
			
		||||
bool command_proc(uint8_t code);
 | 
			
		||||
#else
 | 
			
		||||
#define command_proc(code)      false
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								common/debug.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								common/debug.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
 | 
			
		||||
 | 
			
		||||
debug_config_t debug_config = {
 | 
			
		||||
/* GCC Bug 10676 - Using unnamed fields in initializers
 | 
			
		||||
 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 */
 | 
			
		||||
#if GCC_VERSION >= 40600
 | 
			
		||||
    .enable = false,
 | 
			
		||||
    .matrix = false,
 | 
			
		||||
    .keyboard = false,
 | 
			
		||||
    .mouse = false,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
#else
 | 
			
		||||
    {
 | 
			
		||||
        false,  // .enable
 | 
			
		||||
        false,  // .matrix
 | 
			
		||||
        false,  // .keyboard
 | 
			
		||||
        false,  // .mouse
 | 
			
		||||
        0       // .reserved
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										117
									
								
								common/debug.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								common/debug.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DEBUG_H
 | 
			
		||||
#define DEBUG_H 1
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "print.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Debug output control
 | 
			
		||||
 */
 | 
			
		||||
typedef union {
 | 
			
		||||
    struct {
 | 
			
		||||
        bool enable:1;
 | 
			
		||||
        bool matrix:1;
 | 
			
		||||
        bool keyboard:1;
 | 
			
		||||
        bool mouse:1;
 | 
			
		||||
        uint8_t reserved:4;
 | 
			
		||||
    };
 | 
			
		||||
    uint8_t raw;
 | 
			
		||||
} debug_config_t;
 | 
			
		||||
 | 
			
		||||
extern debug_config_t debug_config;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* for backward compatibility */
 | 
			
		||||
#define debug_enable    (debug_config.enable)
 | 
			
		||||
#define debug_matrix    (debug_config.matrix)
 | 
			
		||||
#define debug_keyboard  (debug_config.keyboard)
 | 
			
		||||
#define debug_mouse     (debug_config.mouse)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Debug print utils
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NO_DEBUG
 | 
			
		||||
 | 
			
		||||
#define dprint(s)                   do { if (debug_enable) print(s); } while (0)
 | 
			
		||||
#define dprintln(s)                 do { if (debug_enable) println(s); } while (0)
 | 
			
		||||
#define dprintf(fmt, ...)           do { if (debug_enable) xprintf(fmt, ##__VA_ARGS__); } while (0)
 | 
			
		||||
#define dmsg(s)                     dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s))
 | 
			
		||||
 | 
			
		||||
/* Deprecated. DO NOT USE these anymore, use dprintf instead. */
 | 
			
		||||
#define debug(s)                    do { if (debug_enable) print(s); } while (0)
 | 
			
		||||
#define debugln(s)                  do { if (debug_enable) println(s); } while (0)
 | 
			
		||||
#define debug_msg(s)                do { \
 | 
			
		||||
    if (debug_enable) { \
 | 
			
		||||
        print(__FILE__); print(" at "); print_dec(__LINE__); print(" in "); print(": "); print(s); \
 | 
			
		||||
    } \
 | 
			
		||||
} while (0)
 | 
			
		||||
#define debug_dec(data)             do { if (debug_enable) print_dec(data); } while (0)
 | 
			
		||||
#define debug_decs(data)            do { if (debug_enable) print_decs(data); } while (0)
 | 
			
		||||
#define debug_hex4(data)            do { if (debug_enable) print_hex4(data); } while (0)
 | 
			
		||||
#define debug_hex8(data)            do { if (debug_enable) print_hex8(data); } while (0)
 | 
			
		||||
#define debug_hex16(data)           do { if (debug_enable) print_hex16(data); } while (0)
 | 
			
		||||
#define debug_hex32(data)           do { if (debug_enable) print_hex32(data); } while (0)
 | 
			
		||||
#define debug_bin8(data)            do { if (debug_enable) print_bin8(data); } while (0)
 | 
			
		||||
#define debug_bin16(data)           do { if (debug_enable) print_bin16(data); } while (0)
 | 
			
		||||
#define debug_bin32(data)           do { if (debug_enable) print_bin32(data); } while (0)
 | 
			
		||||
#define debug_bin_reverse8(data)    do { if (debug_enable) print_bin_reverse8(data); } while (0)
 | 
			
		||||
#define debug_bin_reverse16(data)   do { if (debug_enable) print_bin_reverse16(data); } while (0)
 | 
			
		||||
#define debug_bin_reverse32(data)   do { if (debug_enable) print_bin_reverse32(data); } while (0)
 | 
			
		||||
#define debug_hex(data)             debug_hex8(data)
 | 
			
		||||
#define debug_bin(data)             debug_bin8(data)
 | 
			
		||||
#define debug_bin_reverse(data)     debug_bin8(data)
 | 
			
		||||
 | 
			
		||||
#else /* NO_DEBUG */
 | 
			
		||||
 | 
			
		||||
#define dprint(s)
 | 
			
		||||
#define dprintln(s)
 | 
			
		||||
#define dprintf(fmt, ...)
 | 
			
		||||
#define dmsg(s)
 | 
			
		||||
#define debug(s)
 | 
			
		||||
#define debugln(s)
 | 
			
		||||
#define debug_msg(s)
 | 
			
		||||
#define debug_dec(data)
 | 
			
		||||
#define debug_decs(data)
 | 
			
		||||
#define debug_hex4(data)
 | 
			
		||||
#define debug_hex8(data)
 | 
			
		||||
#define debug_hex16(data)
 | 
			
		||||
#define debug_hex32(data)
 | 
			
		||||
#define debug_bin8(data)
 | 
			
		||||
#define debug_bin16(data)
 | 
			
		||||
#define debug_bin32(data)
 | 
			
		||||
#define debug_bin_reverse8(data)
 | 
			
		||||
#define debug_bin_reverse16(data)
 | 
			
		||||
#define debug_bin_reverse32(data)
 | 
			
		||||
#define debug_hex(data)
 | 
			
		||||
#define debug_bin(data)
 | 
			
		||||
#define debug_bin_reverse(data)
 | 
			
		||||
 | 
			
		||||
#endif /* NO_DEBUG */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										75
									
								
								common/eeconfig.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								common/eeconfig.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef EECONFIG_H
 | 
			
		||||
#define EECONFIG_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define EECONFIG_MAGIC_NUMBER                       (uint16_t)0xFEED
 | 
			
		||||
 | 
			
		||||
/* eeprom parameteter address */
 | 
			
		||||
#define EECONFIG_MAGIC                              (uint16_t *)0
 | 
			
		||||
#define EECONFIG_DEBUG                              (uint8_t *)2
 | 
			
		||||
#define EECONFIG_DEFAULT_LAYER                      (uint8_t *)3
 | 
			
		||||
#define EECONFIG_KEYMAP                             (uint8_t *)4
 | 
			
		||||
#define EECONFIG_MOUSEKEY_ACCEL                     (uint8_t *)5
 | 
			
		||||
#define EECONFIG_BACKLIGHT                          (uint8_t *)6
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* debug bit */
 | 
			
		||||
#define EECONFIG_DEBUG_ENABLE                       (1<<0)
 | 
			
		||||
#define EECONFIG_DEBUG_MATRIX                       (1<<1)
 | 
			
		||||
#define EECONFIG_DEBUG_KEYBOARD                     (1<<2)
 | 
			
		||||
#define EECONFIG_DEBUG_MOUSE                        (1<<3)
 | 
			
		||||
 | 
			
		||||
/* keyconf bit */
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK       (1<<0)
 | 
			
		||||
#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL         (1<<1)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_LALT_LGUI              (1<<2)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_RALT_RGUI              (1<<3)
 | 
			
		||||
#define EECONFIG_KEYMAP_NO_GUI                      (1<<4)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC              (1<<5)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE    (1<<6)
 | 
			
		||||
#define EECONFIG_KEYMAP_NKRO                        (1<<7)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool eeconfig_is_enabled(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_init(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_enable(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_disable(void);
 | 
			
		||||
 | 
			
		||||
uint8_t eeconfig_read_debug(void);
 | 
			
		||||
void eeconfig_write_debug(uint8_t val);
 | 
			
		||||
 | 
			
		||||
uint8_t eeconfig_read_default_layer(void);
 | 
			
		||||
void eeconfig_write_default_layer(uint8_t val);
 | 
			
		||||
 | 
			
		||||
uint8_t eeconfig_read_keymap(void);
 | 
			
		||||
void eeconfig_write_keymap(uint8_t val);
 | 
			
		||||
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
uint8_t eeconfig_read_backlight(void);
 | 
			
		||||
void eeconfig_write_backlight(uint8_t val);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										97
									
								
								common/host.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								common/host.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
//#include <avr/interrupt.h>
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
bool keyboard_nkro = true;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static host_driver_t *driver;
 | 
			
		||||
static uint16_t last_system_report = 0;
 | 
			
		||||
static uint16_t last_consumer_report = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void host_set_driver(host_driver_t *d)
 | 
			
		||||
{
 | 
			
		||||
    driver = d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
host_driver_t *host_get_driver(void)
 | 
			
		||||
{
 | 
			
		||||
    return driver;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t host_keyboard_leds(void)
 | 
			
		||||
{
 | 
			
		||||
    if (!driver) return 0;
 | 
			
		||||
    return (*driver->keyboard_leds)();
 | 
			
		||||
}
 | 
			
		||||
/* send report */
 | 
			
		||||
void host_keyboard_send(report_keyboard_t *report)
 | 
			
		||||
{
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_keyboard)(report);
 | 
			
		||||
 | 
			
		||||
    if (debug_keyboard) {
 | 
			
		||||
        dprint("keyboard_report: ");
 | 
			
		||||
        for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
 | 
			
		||||
            dprintf("%02X ", report->raw[i]);
 | 
			
		||||
        }
 | 
			
		||||
        dprint("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void host_mouse_send(report_mouse_t *report)
 | 
			
		||||
{
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_mouse)(report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void host_system_send(uint16_t report)
 | 
			
		||||
{
 | 
			
		||||
    if (report == last_system_report) return;
 | 
			
		||||
    last_system_report = report;
 | 
			
		||||
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_system)(report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void host_consumer_send(uint16_t report)
 | 
			
		||||
{
 | 
			
		||||
    if (report == last_consumer_report) return;
 | 
			
		||||
    last_consumer_report = report;
 | 
			
		||||
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_consumer)(report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_sysytem_report(void)
 | 
			
		||||
{
 | 
			
		||||
    return last_system_report;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_consumer_report(void)
 | 
			
		||||
{
 | 
			
		||||
    return last_consumer_report;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								common/host.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								common/host.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef HOST_H
 | 
			
		||||
#define HOST_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "report.h"
 | 
			
		||||
#include "host_driver.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
extern bool keyboard_nkro;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern uint8_t keyboard_idle;
 | 
			
		||||
extern uint8_t keyboard_protocol;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* host driver */
 | 
			
		||||
void host_set_driver(host_driver_t *driver);
 | 
			
		||||
host_driver_t *host_get_driver(void);
 | 
			
		||||
 | 
			
		||||
/* host driver interface */
 | 
			
		||||
uint8_t host_keyboard_leds(void);
 | 
			
		||||
void host_keyboard_send(report_keyboard_t *report);
 | 
			
		||||
void host_mouse_send(report_mouse_t *report);
 | 
			
		||||
void host_system_send(uint16_t data);
 | 
			
		||||
void host_consumer_send(uint16_t data);
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_sysytem_report(void);
 | 
			
		||||
uint16_t host_last_consumer_report(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										33
									
								
								common/host_driver.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								common/host_driver.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef HOST_DRIVER_H
 | 
			
		||||
#define HOST_DRIVER_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "report.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t (*keyboard_leds)(void);
 | 
			
		||||
    void (*send_keyboard)(report_keyboard_t *);
 | 
			
		||||
    void (*send_mouse)(report_mouse_t *);
 | 
			
		||||
    void (*send_system)(uint16_t);
 | 
			
		||||
    void (*send_consumer)(uint16_t);
 | 
			
		||||
} host_driver_t;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										150
									
								
								common/keyboard.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								common/keyboard.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,150 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "sendchar.h"
 | 
			
		||||
#include "bootmagic.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "backlight.h"
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
#   include "mousekey.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
#   include "ps2_mouse.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
#include "serial_mouse.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
static bool has_ghost_in_row(uint8_t row)
 | 
			
		||||
{
 | 
			
		||||
    matrix_row_t matrix_row = matrix_get_row(row);
 | 
			
		||||
    // No ghost exists when less than 2 keys are down on the row
 | 
			
		||||
    if (((matrix_row - 1) & matrix_row) == 0)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // Ghost occurs when the row shares column line with other row
 | 
			
		||||
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
 | 
			
		||||
        if (i != row && (matrix_get_row(i) & matrix_row))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void keyboard_init(void)
 | 
			
		||||
{
 | 
			
		||||
    timer_init();
 | 
			
		||||
    matrix_init();
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
    ps2_mouse_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
    serial_mouse_init();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
    bootmagic();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
    backlight_init();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Do keyboard routine jobs: scan mantrix, light LEDs, ...
 | 
			
		||||
 * This is repeatedly called as fast as possible.
 | 
			
		||||
 */
 | 
			
		||||
void keyboard_task(void)
 | 
			
		||||
{
 | 
			
		||||
    static matrix_row_t matrix_prev[MATRIX_ROWS];
 | 
			
		||||
    static uint8_t led_status = 0;
 | 
			
		||||
    matrix_row_t matrix_row = 0;
 | 
			
		||||
    matrix_row_t matrix_change = 0;
 | 
			
		||||
 | 
			
		||||
    matrix_scan();
 | 
			
		||||
    for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
 | 
			
		||||
        matrix_row = matrix_get_row(r);
 | 
			
		||||
        matrix_change = matrix_row ^ matrix_prev[r];
 | 
			
		||||
        if (matrix_change) {
 | 
			
		||||
            if (debug_matrix) matrix_print();
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
            if (has_ghost_in_row(r)) {
 | 
			
		||||
                matrix_prev[r] = matrix_row;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            for (uint8_t c = 0; c < MATRIX_COLS; c++) {
 | 
			
		||||
                if (matrix_change & ((matrix_row_t)1<<c)) {
 | 
			
		||||
                    action_exec((keyevent_t){
 | 
			
		||||
                        .key = (keypos_t){ .row = r, .col = c },
 | 
			
		||||
                        .pressed = (matrix_row & ((matrix_row_t)1<<c)),
 | 
			
		||||
                        .time = (timer_read() | 1) /* time should not be 0 */
 | 
			
		||||
                    });
 | 
			
		||||
                    // record a processed key
 | 
			
		||||
                    matrix_prev[r] ^= ((matrix_row_t)1<<c);
 | 
			
		||||
                    // process a key per task call
 | 
			
		||||
                    goto MATRIX_LOOP_END;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // call with pseudo tick event when no real key event.
 | 
			
		||||
    action_exec(TICK);
 | 
			
		||||
 | 
			
		||||
MATRIX_LOOP_END:
 | 
			
		||||
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    // mousekey repeat & acceleration
 | 
			
		||||
    mousekey_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
    ps2_mouse_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
        serial_mouse_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // update LED
 | 
			
		||||
    if (led_status != host_keyboard_leds()) {
 | 
			
		||||
        led_status = host_keyboard_leds();
 | 
			
		||||
        keyboard_set_leds(led_status);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_set_leds(uint8_t leds)
 | 
			
		||||
{
 | 
			
		||||
    if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
 | 
			
		||||
    led_set(leds);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								common/keyboard.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								common/keyboard.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef KEYBOARD_H
 | 
			
		||||
#define KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* key matrix position */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t col;
 | 
			
		||||
    uint8_t row;
 | 
			
		||||
} keypos_t;
 | 
			
		||||
 | 
			
		||||
/* key event */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keypos_t key;
 | 
			
		||||
    bool     pressed;
 | 
			
		||||
    uint16_t time;
 | 
			
		||||
} keyevent_t;
 | 
			
		||||
 | 
			
		||||
/* equivalent test of keypos_t */
 | 
			
		||||
#define KEYEQ(keya, keyb)       ((keya).row == (keyb).row && (keya).col == (keyb).col)
 | 
			
		||||
 | 
			
		||||
/* Rules for No Event:
 | 
			
		||||
 * 1) (time == 0) to handle (keyevent_t){} as empty event
 | 
			
		||||
 * 2) Matrix(255, 255) to make TICK event available
 | 
			
		||||
 */
 | 
			
		||||
static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); }
 | 
			
		||||
static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); }
 | 
			
		||||
static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); }
 | 
			
		||||
 | 
			
		||||
/* Tick event */
 | 
			
		||||
#define TICK                    (keyevent_t){           \
 | 
			
		||||
    .key = (keypos_t){ .row = 255, .col = 255 },           \
 | 
			
		||||
    .pressed = false,                                   \
 | 
			
		||||
    .time = (timer_read() | 1)                          \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void keyboard_init(void);
 | 
			
		||||
void keyboard_task(void);
 | 
			
		||||
void keyboard_set_leds(uint8_t leds);
 | 
			
		||||
 | 
			
		||||
__attribute__ ((weak)) void matrix_power_up(void) {}
 | 
			
		||||
__attribute__ ((weak)) void matrix_power_down(void) {}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										489
									
								
								common/keycode.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										489
									
								
								common/keycode.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,489 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes
 | 
			
		||||
 * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
 | 
			
		||||
 */
 | 
			
		||||
#ifndef KEYCODE_H
 | 
			
		||||
#define KEYCODE_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define IS_ERROR(code)           (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
 | 
			
		||||
#define IS_ANY(code)             (KC_A         <= (code) && (code) <= 0xFF)
 | 
			
		||||
#define IS_KEY(code)             (KC_A         <= (code) && (code) <= KC_EXSEL)
 | 
			
		||||
#define IS_MOD(code)             (KC_LCTRL     <= (code) && (code) <= KC_RGUI)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define IS_SPECIAL(code)         ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
 | 
			
		||||
#define IS_SYSTEM(code)          (KC_PWR       <= (code) && (code) <= KC_WAKE)
 | 
			
		||||
#define IS_CONSUMER(code)        (KC_MUTE      <= (code) && (code) <= KC_WFAV)
 | 
			
		||||
#define IS_FN(code)              (KC_FN0       <= (code) && (code) <= KC_FN31)
 | 
			
		||||
#define IS_MOUSEKEY(code)        (KC_MS_UP     <= (code) && (code) <= KC_MS_ACCEL2)
 | 
			
		||||
#define IS_MOUSEKEY_MOVE(code)   (KC_MS_UP     <= (code) && (code) <= KC_MS_RIGHT)
 | 
			
		||||
#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1   <= (code) && (code) <= KC_MS_BTN5)
 | 
			
		||||
#define IS_MOUSEKEY_WHEEL(code)  (KC_MS_WH_UP  <= (code) && (code) <= KC_MS_WH_RIGHT)
 | 
			
		||||
#define IS_MOUSEKEY_ACCEL(code)  (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
 | 
			
		||||
 | 
			
		||||
#define MOD_BIT(code)   (1<<MOD_INDEX(code))
 | 
			
		||||
#define MOD_INDEX(code) ((code) & 0x07)
 | 
			
		||||
#define FN_BIT(code)    (1<<FN_INDEX(code))
 | 
			
		||||
#define FN_INDEX(code)  ((code) - KC_FN0)
 | 
			
		||||
#define FN_MIN          KC_FN0
 | 
			
		||||
#define FN_MAX          KC_FN31
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Short names for ease of definition of keymap
 | 
			
		||||
 */
 | 
			
		||||
#define KC_LCTL KC_LCTRL
 | 
			
		||||
#define KC_RCTL KC_RCTRL
 | 
			
		||||
#define KC_LSFT KC_LSHIFT
 | 
			
		||||
#define KC_RSFT KC_RSHIFT
 | 
			
		||||
#define KC_ESC  KC_ESCAPE
 | 
			
		||||
#define KC_BSPC KC_BSPACE
 | 
			
		||||
#define KC_ENT  KC_ENTER
 | 
			
		||||
#define KC_DEL  KC_DELETE
 | 
			
		||||
#define KC_INS  KC_INSERT
 | 
			
		||||
#define KC_CAPS KC_CAPSLOCK
 | 
			
		||||
#define KC_CLCK KC_CAPSLOCK
 | 
			
		||||
#define KC_RGHT KC_RIGHT
 | 
			
		||||
#define KC_PGDN KC_PGDOWN
 | 
			
		||||
#define KC_PSCR KC_PSCREEN
 | 
			
		||||
#define KC_SLCK KC_SCROLLLOCK
 | 
			
		||||
#define KC_PAUS KC_PAUSE
 | 
			
		||||
#define KC_BRK  KC_PAUSE
 | 
			
		||||
#define KC_NLCK KC_NUMLOCK
 | 
			
		||||
#define KC_SPC  KC_SPACE
 | 
			
		||||
#define KC_MINS KC_MINUS
 | 
			
		||||
#define KC_EQL  KC_EQUAL
 | 
			
		||||
#define KC_GRV  KC_GRAVE
 | 
			
		||||
#define KC_RBRC KC_RBRACKET
 | 
			
		||||
#define KC_LBRC KC_LBRACKET
 | 
			
		||||
#define KC_COMM KC_COMMA
 | 
			
		||||
#define KC_BSLS KC_BSLASH
 | 
			
		||||
#define KC_SLSH KC_SLASH
 | 
			
		||||
#define KC_SCLN KC_SCOLON
 | 
			
		||||
#define KC_QUOT KC_QUOTE
 | 
			
		||||
#define KC_APP  KC_APPLICATION
 | 
			
		||||
#define KC_NUHS KC_NONUS_HASH
 | 
			
		||||
#define KC_NUBS KC_NONUS_BSLASH
 | 
			
		||||
#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_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_HENK KC_INT4
 | 
			
		||||
#define KC_MHEN KC_INT5
 | 
			
		||||
/* Keypad */
 | 
			
		||||
#define KC_P1   KC_KP_1
 | 
			
		||||
#define KC_P2   KC_KP_2
 | 
			
		||||
#define KC_P3   KC_KP_3
 | 
			
		||||
#define KC_P4   KC_KP_4
 | 
			
		||||
#define KC_P5   KC_KP_5
 | 
			
		||||
#define KC_P6   KC_KP_6
 | 
			
		||||
#define KC_P7   KC_KP_7
 | 
			
		||||
#define KC_P8   KC_KP_8
 | 
			
		||||
#define KC_P9   KC_KP_9
 | 
			
		||||
#define KC_P0   KC_KP_0
 | 
			
		||||
#define KC_PDOT KC_KP_DOT
 | 
			
		||||
#define KC_PCMM KC_KP_COMMA
 | 
			
		||||
#define KC_PSLS KC_KP_SLASH
 | 
			
		||||
#define KC_PAST KC_KP_ASTERISK
 | 
			
		||||
#define KC_PMNS KC_KP_MINUS
 | 
			
		||||
#define KC_PPLS KC_KP_PLUS
 | 
			
		||||
#define KC_PEQL KC_KP_EQUAL
 | 
			
		||||
#define KC_PENT KC_KP_ENTER
 | 
			
		||||
/* Mousekey */
 | 
			
		||||
#define KC_MS_U KC_MS_UP
 | 
			
		||||
#define KC_MS_D KC_MS_DOWN
 | 
			
		||||
#define KC_MS_L KC_MS_LEFT
 | 
			
		||||
#define KC_MS_R KC_MS_RIGHT
 | 
			
		||||
#define KC_BTN1 KC_MS_BTN1
 | 
			
		||||
#define KC_BTN2 KC_MS_BTN2
 | 
			
		||||
#define KC_BTN3 KC_MS_BTN3
 | 
			
		||||
#define KC_BTN4 KC_MS_BTN4
 | 
			
		||||
#define KC_BTN5 KC_MS_BTN5
 | 
			
		||||
#define KC_WH_U KC_MS_WH_UP
 | 
			
		||||
#define KC_WH_D KC_MS_WH_DOWN
 | 
			
		||||
#define KC_WH_L KC_MS_WH_LEFT
 | 
			
		||||
#define KC_WH_R KC_MS_WH_RIGHT
 | 
			
		||||
#define KC_ACL0 KC_MS_ACCEL0
 | 
			
		||||
#define KC_ACL1 KC_MS_ACCEL1
 | 
			
		||||
#define KC_ACL2 KC_MS_ACCEL2
 | 
			
		||||
/* Sytem Control */
 | 
			
		||||
#define KC_PWR  KC_SYSTEM_POWER
 | 
			
		||||
#define KC_SLEP KC_SYSTEM_SLEEP
 | 
			
		||||
#define KC_WAKE KC_SYSTEM_WAKE
 | 
			
		||||
/* Consumer Page */
 | 
			
		||||
#define KC_MUTE KC_AUDIO_MUTE
 | 
			
		||||
#define KC_VOLU KC_AUDIO_VOL_UP
 | 
			
		||||
#define KC_VOLD KC_AUDIO_VOL_DOWN
 | 
			
		||||
#define KC_MNXT KC_MEDIA_NEXT_TRACK
 | 
			
		||||
#define KC_MPRV KC_MEDIA_PREV_TRACK
 | 
			
		||||
#define KC_MFFD KC_MEDIA_FAST_FORWARD
 | 
			
		||||
#define KC_MRWD KC_MEDIA_REWIND
 | 
			
		||||
#define KC_MSTP KC_MEDIA_STOP
 | 
			
		||||
#define KC_MPLY KC_MEDIA_PLAY_PAUSE
 | 
			
		||||
#define KC_MSEL KC_MEDIA_SELECT
 | 
			
		||||
#define KC_EJCT KC_MEDIA_EJECT
 | 
			
		||||
#define KC_MAIL KC_MAIL
 | 
			
		||||
#define KC_CALC KC_CALCULATOR
 | 
			
		||||
#define KC_MYCM KC_MY_COMPUTER
 | 
			
		||||
#define KC_WSCH KC_WWW_SEARCH
 | 
			
		||||
#define KC_WHOM KC_WWW_HOME
 | 
			
		||||
#define KC_WBAK KC_WWW_BACK
 | 
			
		||||
#define KC_WFWD KC_WWW_FORWARD
 | 
			
		||||
#define KC_WSTP KC_WWW_STOP
 | 
			
		||||
#define KC_WREF KC_WWW_REFRESH
 | 
			
		||||
#define KC_WFAV KC_WWW_FAVORITES
 | 
			
		||||
/* Transparent */
 | 
			
		||||
#define KC_TRANSPARENT  1
 | 
			
		||||
#define KC_TRNS KC_TRANSPARENT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* USB HID Keyboard/Keypad Usage(0x07) */
 | 
			
		||||
enum hid_keyboard_keypad_usage {
 | 
			
		||||
    KC_NO               = 0x00,
 | 
			
		||||
    KC_ROLL_OVER,
 | 
			
		||||
    KC_POST_FAIL,
 | 
			
		||||
    KC_UNDEFINED,
 | 
			
		||||
    KC_A,
 | 
			
		||||
    KC_B,
 | 
			
		||||
    KC_C,
 | 
			
		||||
    KC_D,
 | 
			
		||||
    KC_E,
 | 
			
		||||
    KC_F,
 | 
			
		||||
    KC_G,
 | 
			
		||||
    KC_H,
 | 
			
		||||
    KC_I,
 | 
			
		||||
    KC_J,
 | 
			
		||||
    KC_K,
 | 
			
		||||
    KC_L,
 | 
			
		||||
    KC_M,               /* 0x10 */
 | 
			
		||||
    KC_N,
 | 
			
		||||
    KC_O,
 | 
			
		||||
    KC_P,
 | 
			
		||||
    KC_Q,
 | 
			
		||||
    KC_R,
 | 
			
		||||
    KC_S,
 | 
			
		||||
    KC_T,
 | 
			
		||||
    KC_U,
 | 
			
		||||
    KC_V,
 | 
			
		||||
    KC_W,
 | 
			
		||||
    KC_X,
 | 
			
		||||
    KC_Y,
 | 
			
		||||
    KC_Z,
 | 
			
		||||
    KC_1,
 | 
			
		||||
    KC_2,
 | 
			
		||||
    KC_3,               /* 0x20 */
 | 
			
		||||
    KC_4,
 | 
			
		||||
    KC_5,
 | 
			
		||||
    KC_6,
 | 
			
		||||
    KC_7,
 | 
			
		||||
    KC_8,
 | 
			
		||||
    KC_9,
 | 
			
		||||
    KC_0,
 | 
			
		||||
    KC_ENTER,
 | 
			
		||||
    KC_ESCAPE,
 | 
			
		||||
    KC_BSPACE,
 | 
			
		||||
    KC_TAB,
 | 
			
		||||
    KC_SPACE,
 | 
			
		||||
    KC_MINUS,
 | 
			
		||||
    KC_EQUAL,
 | 
			
		||||
    KC_LBRACKET,
 | 
			
		||||
    KC_RBRACKET,        /* 0x30 */
 | 
			
		||||
    KC_BSLASH,          /* \ (and |) */
 | 
			
		||||
    KC_NONUS_HASH,      /* Non-US # and ~ */
 | 
			
		||||
    KC_SCOLON,          /* ; (and :) */
 | 
			
		||||
    KC_QUOTE,           /* ' and " */
 | 
			
		||||
    KC_GRAVE,           /* Grave accent and tilde */
 | 
			
		||||
    KC_COMMA,           /* , and < */
 | 
			
		||||
    KC_DOT,             /* . and > */
 | 
			
		||||
    KC_SLASH,           /* / and ? */
 | 
			
		||||
    KC_CAPSLOCK,
 | 
			
		||||
    KC_F1,
 | 
			
		||||
    KC_F2,
 | 
			
		||||
    KC_F3,
 | 
			
		||||
    KC_F4,
 | 
			
		||||
    KC_F5,
 | 
			
		||||
    KC_F6,
 | 
			
		||||
    KC_F7,              /* 0x40 */
 | 
			
		||||
    KC_F8,
 | 
			
		||||
    KC_F9,
 | 
			
		||||
    KC_F10,
 | 
			
		||||
    KC_F11,
 | 
			
		||||
    KC_F12,
 | 
			
		||||
    KC_PSCREEN,
 | 
			
		||||
    KC_SCROLLLOCK,
 | 
			
		||||
    KC_PAUSE,
 | 
			
		||||
    KC_INSERT,
 | 
			
		||||
    KC_HOME,
 | 
			
		||||
    KC_PGUP,
 | 
			
		||||
    KC_DELETE,
 | 
			
		||||
    KC_END,
 | 
			
		||||
    KC_PGDOWN,
 | 
			
		||||
    KC_RIGHT,
 | 
			
		||||
    KC_LEFT,            /* 0x50 */
 | 
			
		||||
    KC_DOWN,
 | 
			
		||||
    KC_UP,
 | 
			
		||||
    KC_NUMLOCK,
 | 
			
		||||
    KC_KP_SLASH,
 | 
			
		||||
    KC_KP_ASTERISK,
 | 
			
		||||
    KC_KP_MINUS,
 | 
			
		||||
    KC_KP_PLUS,
 | 
			
		||||
    KC_KP_ENTER,
 | 
			
		||||
    KC_KP_1,
 | 
			
		||||
    KC_KP_2,
 | 
			
		||||
    KC_KP_3,
 | 
			
		||||
    KC_KP_4,
 | 
			
		||||
    KC_KP_5,
 | 
			
		||||
    KC_KP_6,
 | 
			
		||||
    KC_KP_7,
 | 
			
		||||
    KC_KP_8,            /* 0x60 */
 | 
			
		||||
    KC_KP_9,
 | 
			
		||||
    KC_KP_0,
 | 
			
		||||
    KC_KP_DOT,
 | 
			
		||||
    KC_NONUS_BSLASH,    /* Non-US \ and | */
 | 
			
		||||
    KC_APPLICATION,
 | 
			
		||||
    KC_POWER,
 | 
			
		||||
    KC_KP_EQUAL,
 | 
			
		||||
    KC_F13,
 | 
			
		||||
    KC_F14,
 | 
			
		||||
    KC_F15,
 | 
			
		||||
    KC_F16,
 | 
			
		||||
    KC_F17,
 | 
			
		||||
    KC_F18,
 | 
			
		||||
    KC_F19,
 | 
			
		||||
    KC_F20,
 | 
			
		||||
    KC_F21,             /* 0x70 */
 | 
			
		||||
    KC_F22,
 | 
			
		||||
    KC_F23,
 | 
			
		||||
    KC_F24,
 | 
			
		||||
    KC_EXECUTE,
 | 
			
		||||
    KC_HELP,
 | 
			
		||||
    KC_MENU,
 | 
			
		||||
    KC_SELECT,
 | 
			
		||||
    KC_STOP,
 | 
			
		||||
    KC_AGAIN,
 | 
			
		||||
    KC_UNDO,
 | 
			
		||||
    KC_CUT,
 | 
			
		||||
    KC_COPY,
 | 
			
		||||
    KC_PASTE,
 | 
			
		||||
    KC_FIND,
 | 
			
		||||
    KC__MUTE,
 | 
			
		||||
    KC__VOLUP,          /* 0x80 */
 | 
			
		||||
    KC__VOLDOWN,
 | 
			
		||||
    KC_LOCKING_CAPS,    /* locking Caps Lock */
 | 
			
		||||
    KC_LOCKING_NUM,     /* locking Num Lock */
 | 
			
		||||
    KC_LOCKING_SCROLL,  /* locking Scroll Lock */
 | 
			
		||||
    KC_KP_COMMA,
 | 
			
		||||
    KC_KP_EQUAL_AS400,  /* equal sign on AS/400 */
 | 
			
		||||
    KC_INT1,
 | 
			
		||||
    KC_INT2,
 | 
			
		||||
    KC_INT3,
 | 
			
		||||
    KC_INT4,
 | 
			
		||||
    KC_INT5,
 | 
			
		||||
    KC_INT6,
 | 
			
		||||
    KC_INT7,
 | 
			
		||||
    KC_INT8,
 | 
			
		||||
    KC_INT9,
 | 
			
		||||
    KC_LANG1,           /* 0x90 */
 | 
			
		||||
    KC_LANG2,
 | 
			
		||||
    KC_LANG3,
 | 
			
		||||
    KC_LANG4,
 | 
			
		||||
    KC_LANG5,
 | 
			
		||||
    KC_LANG6,
 | 
			
		||||
    KC_LANG7,
 | 
			
		||||
    KC_LANG8,
 | 
			
		||||
    KC_LANG9,
 | 
			
		||||
    KC_ALT_ERASE,
 | 
			
		||||
    KC_SYSREQ,
 | 
			
		||||
    KC_CANCEL,
 | 
			
		||||
    KC_CLEAR,
 | 
			
		||||
    KC_PRIOR,
 | 
			
		||||
    KC_RETURN,
 | 
			
		||||
    KC_SEPARATOR,
 | 
			
		||||
    KC_OUT,             /* 0xA0 */
 | 
			
		||||
    KC_OPER,
 | 
			
		||||
    KC_CLEAR_AGAIN,
 | 
			
		||||
    KC_CRSEL,
 | 
			
		||||
    KC_EXSEL,           /* 0xA4 */
 | 
			
		||||
 | 
			
		||||
    /* NOTE: 0xA5-DF are used for internal special purpose */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    /* NOTE: Following codes(0xB0-DD) are not used. Leave them for reference. */
 | 
			
		||||
    KC_KP_00            = 0xB0,
 | 
			
		||||
    KC_KP_000,
 | 
			
		||||
    KC_THOUSANDS_SEPARATOR,
 | 
			
		||||
    KC_DECIMAL_SEPARATOR,
 | 
			
		||||
    KC_CURRENCY_UNIT,
 | 
			
		||||
    KC_CURRENCY_SUB_UNIT,
 | 
			
		||||
    KC_KP_LPAREN,
 | 
			
		||||
    KC_KP_RPAREN,
 | 
			
		||||
    KC_KP_LCBRACKET,    /* { */
 | 
			
		||||
    KC_KP_RCBRACKET,    /* } */
 | 
			
		||||
    KC_KP_TAB,
 | 
			
		||||
    KC_KP_BSPACE,
 | 
			
		||||
    KC_KP_A,
 | 
			
		||||
    KC_KP_B,
 | 
			
		||||
    KC_KP_C,
 | 
			
		||||
    KC_KP_D,
 | 
			
		||||
    KC_KP_E,            /* 0xC0 */
 | 
			
		||||
    KC_KP_F,
 | 
			
		||||
    KC_KP_XOR,
 | 
			
		||||
    KC_KP_HAT,
 | 
			
		||||
    KC_KP_PERC,
 | 
			
		||||
    KC_KP_LT,
 | 
			
		||||
    KC_KP_GT,
 | 
			
		||||
    KC_KP_AND,
 | 
			
		||||
    KC_KP_LAZYAND,
 | 
			
		||||
    KC_KP_OR,
 | 
			
		||||
    KC_KP_LAZYOR,
 | 
			
		||||
    KC_KP_COLON,
 | 
			
		||||
    KC_KP_HASH,
 | 
			
		||||
    KC_KP_SPACE,
 | 
			
		||||
    KC_KP_ATMARK,
 | 
			
		||||
    KC_KP_EXCLAMATION,
 | 
			
		||||
    KC_KP_MEM_STORE,    /* 0xD0 */
 | 
			
		||||
    KC_KP_MEM_RECALL,
 | 
			
		||||
    KC_KP_MEM_CLEAR,
 | 
			
		||||
    KC_KP_MEM_ADD,
 | 
			
		||||
    KC_KP_MEM_SUB,
 | 
			
		||||
    KC_KP_MEM_MUL,
 | 
			
		||||
    KC_KP_MEM_DIV,
 | 
			
		||||
    KC_KP_PLUS_MINUS,
 | 
			
		||||
    KC_KP_CLEAR,
 | 
			
		||||
    KC_KP_CLEAR_ENTRY,
 | 
			
		||||
    KC_KP_BINARY,
 | 
			
		||||
    KC_KP_OCTAL,
 | 
			
		||||
    KC_KP_DECIMAL,
 | 
			
		||||
    KC_KP_HEXADECIMAL,  /* 0xDD */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Modifiers */
 | 
			
		||||
    KC_LCTRL            = 0xE0,
 | 
			
		||||
    KC_LSHIFT,
 | 
			
		||||
    KC_LALT,
 | 
			
		||||
    KC_LGUI,
 | 
			
		||||
    KC_RCTRL,
 | 
			
		||||
    KC_RSHIFT,
 | 
			
		||||
    KC_RALT,
 | 
			
		||||
    KC_RGUI,
 | 
			
		||||
 | 
			
		||||
    /* NOTE: 0xE8-FF are used for internal special purpose */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Special keycodes */
 | 
			
		||||
/* NOTE: 0xA5-DF and 0xE8-FF are used for internal special purpose */
 | 
			
		||||
enum internal_special_keycodes {
 | 
			
		||||
    /* System Control */
 | 
			
		||||
    KC_SYSTEM_POWER     = 0xA5,
 | 
			
		||||
    KC_SYSTEM_SLEEP,
 | 
			
		||||
    KC_SYSTEM_WAKE,
 | 
			
		||||
 | 
			
		||||
    /* Media Control */
 | 
			
		||||
    KC_AUDIO_MUTE,
 | 
			
		||||
    KC_AUDIO_VOL_UP,
 | 
			
		||||
    KC_AUDIO_VOL_DOWN,
 | 
			
		||||
    KC_MEDIA_NEXT_TRACK,
 | 
			
		||||
    KC_MEDIA_PREV_TRACK,
 | 
			
		||||
    KC_MEDIA_STOP,
 | 
			
		||||
    KC_MEDIA_PLAY_PAUSE,
 | 
			
		||||
    KC_MEDIA_SELECT,
 | 
			
		||||
    KC_MEDIA_EJECT,
 | 
			
		||||
    KC_MAIL,
 | 
			
		||||
    KC_CALCULATOR,
 | 
			
		||||
    KC_MY_COMPUTER,
 | 
			
		||||
    KC_WWW_SEARCH,
 | 
			
		||||
    KC_WWW_HOME,
 | 
			
		||||
    KC_WWW_BACK,
 | 
			
		||||
    KC_WWW_FORWARD,
 | 
			
		||||
    KC_WWW_STOP,
 | 
			
		||||
    KC_WWW_REFRESH,
 | 
			
		||||
    KC_WWW_FAVORITES,
 | 
			
		||||
    KC_MEDIA_FAST_FORWARD,
 | 
			
		||||
    KC_MEDIA_REWIND,    /* 0xBC */
 | 
			
		||||
 | 
			
		||||
    /* Fn key */
 | 
			
		||||
    KC_FN0              = 0xC0,
 | 
			
		||||
    KC_FN1,
 | 
			
		||||
    KC_FN2,
 | 
			
		||||
    KC_FN3,
 | 
			
		||||
    KC_FN4,
 | 
			
		||||
    KC_FN5,
 | 
			
		||||
    KC_FN6,
 | 
			
		||||
    KC_FN7,
 | 
			
		||||
    KC_FN8,
 | 
			
		||||
    KC_FN9,
 | 
			
		||||
    KC_FN10,
 | 
			
		||||
    KC_FN11,
 | 
			
		||||
    KC_FN12,
 | 
			
		||||
    KC_FN13,
 | 
			
		||||
    KC_FN14,
 | 
			
		||||
    KC_FN15,
 | 
			
		||||
 | 
			
		||||
    KC_FN16             = 0xD0,
 | 
			
		||||
    KC_FN17,
 | 
			
		||||
    KC_FN18,
 | 
			
		||||
    KC_FN19,
 | 
			
		||||
    KC_FN20,
 | 
			
		||||
    KC_FN21,
 | 
			
		||||
    KC_FN22,
 | 
			
		||||
    KC_FN23,
 | 
			
		||||
    KC_FN24,
 | 
			
		||||
    KC_FN25,
 | 
			
		||||
    KC_FN26,
 | 
			
		||||
    KC_FN27,
 | 
			
		||||
    KC_FN28,
 | 
			
		||||
    KC_FN29,
 | 
			
		||||
    KC_FN30,
 | 
			
		||||
    KC_FN31,            /* 0xDF */
 | 
			
		||||
 | 
			
		||||
    /**************************************/
 | 
			
		||||
    /* 0xE0-E7 for Modifiers. DO NOT USE. */
 | 
			
		||||
    /**************************************/
 | 
			
		||||
 | 
			
		||||
    /* Mousekey */
 | 
			
		||||
    KC_MS_UP            = 0xF0,
 | 
			
		||||
    KC_MS_DOWN,
 | 
			
		||||
    KC_MS_LEFT,
 | 
			
		||||
    KC_MS_RIGHT,
 | 
			
		||||
    KC_MS_BTN1,
 | 
			
		||||
    KC_MS_BTN2,
 | 
			
		||||
    KC_MS_BTN3,
 | 
			
		||||
    KC_MS_BTN4,
 | 
			
		||||
    KC_MS_BTN5,         /* 0xF8 */
 | 
			
		||||
    /* Mousekey wheel */
 | 
			
		||||
    KC_MS_WH_UP,
 | 
			
		||||
    KC_MS_WH_DOWN,
 | 
			
		||||
    KC_MS_WH_LEFT,
 | 
			
		||||
    KC_MS_WH_RIGHT,     /* 0xFC */
 | 
			
		||||
    /* Mousekey accel */
 | 
			
		||||
    KC_MS_ACCEL0,
 | 
			
		||||
    KC_MS_ACCEL1,
 | 
			
		||||
    KC_MS_ACCEL2        /* 0xFF */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* KEYCODE_H */
 | 
			
		||||
							
								
								
									
										185
									
								
								common/keymap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								common/keymap.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,185 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "report.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static action_t keycode_to_action(uint8_t keycode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* converts key to action */
 | 
			
		||||
action_t action_for_key(uint8_t layer, keypos_t key)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t keycode = keymap_key_to_keycode(layer, key);
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
        case KC_FN0 ... KC_FN31:
 | 
			
		||||
            return keymap_fn_to_action(keycode);
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
        case KC_CAPSLOCK:
 | 
			
		||||
        case KC_LOCKING_CAPS:
 | 
			
		||||
            if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
 | 
			
		||||
                return keycode_to_action(KC_LCTL);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(keycode);
 | 
			
		||||
        case KC_LCTL:
 | 
			
		||||
            if (keymap_config.swap_control_capslock) {
 | 
			
		||||
                return keycode_to_action(KC_CAPSLOCK);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_LCTL);
 | 
			
		||||
        case KC_LALT:
 | 
			
		||||
            if (keymap_config.swap_lalt_lgui) {
 | 
			
		||||
                if (keymap_config.no_gui) {
 | 
			
		||||
                    return keycode_to_action(ACTION_NO);
 | 
			
		||||
                }
 | 
			
		||||
                return keycode_to_action(KC_LGUI);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_LALT);
 | 
			
		||||
        case KC_LGUI:
 | 
			
		||||
            if (keymap_config.swap_lalt_lgui) {
 | 
			
		||||
                return keycode_to_action(KC_LALT);
 | 
			
		||||
            }
 | 
			
		||||
            if (keymap_config.no_gui) {
 | 
			
		||||
                return keycode_to_action(ACTION_NO);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_LGUI);
 | 
			
		||||
        case KC_RALT:
 | 
			
		||||
            if (keymap_config.swap_ralt_rgui) {
 | 
			
		||||
                if (keymap_config.no_gui) {
 | 
			
		||||
                    return keycode_to_action(ACTION_NO);
 | 
			
		||||
                }
 | 
			
		||||
                return keycode_to_action(KC_RGUI);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_RALT);
 | 
			
		||||
        case KC_RGUI:
 | 
			
		||||
            if (keymap_config.swap_ralt_rgui) {
 | 
			
		||||
                return keycode_to_action(KC_RALT);
 | 
			
		||||
            }
 | 
			
		||||
            if (keymap_config.no_gui) {
 | 
			
		||||
                return keycode_to_action(ACTION_NO);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_RGUI);
 | 
			
		||||
        case KC_GRAVE:
 | 
			
		||||
            if (keymap_config.swap_grave_esc) {
 | 
			
		||||
                return keycode_to_action(KC_ESC);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_GRAVE);
 | 
			
		||||
        case KC_ESC:
 | 
			
		||||
            if (keymap_config.swap_grave_esc) {
 | 
			
		||||
                return keycode_to_action(KC_GRAVE);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_ESC);
 | 
			
		||||
        case KC_BSLASH:
 | 
			
		||||
            if (keymap_config.swap_backslash_backspace) {
 | 
			
		||||
                return keycode_to_action(KC_BSPACE);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_BSLASH);
 | 
			
		||||
        case KC_BSPACE:
 | 
			
		||||
            if (keymap_config.swap_backslash_backspace) {
 | 
			
		||||
                return keycode_to_action(KC_BSLASH);
 | 
			
		||||
            }
 | 
			
		||||
            return keycode_to_action(KC_BSPACE);
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            return keycode_to_action(keycode);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Macro */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
 | 
			
		||||
{
 | 
			
		||||
    return MACRO_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Function */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
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;
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
        case KC_A ... KC_EXSEL:
 | 
			
		||||
        case KC_LCTRL ... KC_RGUI:
 | 
			
		||||
            action.code = ACTION_KEY(keycode);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
 | 
			
		||||
            action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
 | 
			
		||||
            action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_MS_UP ... KC_MS_ACCEL2:
 | 
			
		||||
            action.code = ACTION_MOUSEKEY(keycode);
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_TRNS:
 | 
			
		||||
            action.code = ACTION_TRANSPARENT;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            action.code = ACTION_NO;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return action;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef USE_LEGACY_KEYMAP
 | 
			
		||||
/*
 | 
			
		||||
 * Legacy keymap support
 | 
			
		||||
 *      Consider using new keymap API instead.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
 | 
			
		||||
{
 | 
			
		||||
    return keymap_get_keycode(layer, key.row, key.col);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Legacy keymap support */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
action_t keymap_fn_to_action(uint8_t keycode)
 | 
			
		||||
{
 | 
			
		||||
    action_t action = { .code = ACTION_NO };
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
        case KC_FN0 ... KC_FN31:
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t layer = keymap_fn_layer(FN_INDEX(keycode));
 | 
			
		||||
                uint8_t key = keymap_fn_keycode(FN_INDEX(keycode));
 | 
			
		||||
                if (key) {
 | 
			
		||||
                    action.code = ACTION_LAYER_TAP_KEY(layer, key);
 | 
			
		||||
                } else {
 | 
			
		||||
                    action.code = ACTION_LAYER_MOMENTARY(layer);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return action;
 | 
			
		||||
        default:
 | 
			
		||||
            return action;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										71
									
								
								common/keymap.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								common/keymap.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef KEYMAP_H
 | 
			
		||||
#define KEYMAP_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "action.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef BOOTMAGIC_ENABLE
 | 
			
		||||
/* NOTE: Not portable. Bit field order depends on implementation */
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint8_t raw;
 | 
			
		||||
    struct {
 | 
			
		||||
        bool swap_control_capslock:1;
 | 
			
		||||
        bool capslock_to_control:1;
 | 
			
		||||
        bool swap_lalt_lgui:1;
 | 
			
		||||
        bool swap_ralt_rgui:1;
 | 
			
		||||
        bool no_gui:1;
 | 
			
		||||
        bool swap_grave_esc:1;
 | 
			
		||||
        bool swap_backslash_backspace:1;
 | 
			
		||||
        bool nkro:1;
 | 
			
		||||
    };
 | 
			
		||||
} keymap_config_t;
 | 
			
		||||
keymap_config_t keymap_config;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* translates key to keycode */
 | 
			
		||||
uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
 | 
			
		||||
 | 
			
		||||
/* translates Fn keycode to action */
 | 
			
		||||
action_t keymap_fn_to_action(uint8_t keycode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef USE_LEGACY_KEYMAP
 | 
			
		||||
/* 
 | 
			
		||||
 * Legacy keymap
 | 
			
		||||
 *      Consider using new keymap API above instead.
 | 
			
		||||
 */
 | 
			
		||||
/* keycode of key */
 | 
			
		||||
__attribute__ ((deprecated))
 | 
			
		||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
 | 
			
		||||
 | 
			
		||||
/* layer to move during press Fn key */
 | 
			
		||||
__attribute__ ((deprecated))
 | 
			
		||||
uint8_t keymap_fn_layer(uint8_t fn_bits);
 | 
			
		||||
 | 
			
		||||
/* keycode to send when release Fn key without using */
 | 
			
		||||
__attribute__ ((deprecated))
 | 
			
		||||
uint8_t keymap_fn_keycode(uint8_t fn_bits);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										33
									
								
								common/led.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								common/led.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef LED_H
 | 
			
		||||
#define LED_H
 | 
			
		||||
#include "stdint.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* keyboard LEDs */
 | 
			
		||||
#define USB_LED_NUM_LOCK                0
 | 
			
		||||
#define USB_LED_CAPS_LOCK               1
 | 
			
		||||
#define USB_LED_SCROLL_LOCK             2
 | 
			
		||||
#define USB_LED_COMPOSE                 3
 | 
			
		||||
#define USB_LED_KANA                    4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void led_set(uint8_t usb_led);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										68
									
								
								common/matrix.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								common/matrix.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef MATRIX_H
 | 
			
		||||
#define MATRIX_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (MATRIX_COLS <= 8)
 | 
			
		||||
typedef  uint8_t    matrix_row_t;
 | 
			
		||||
#elif (MATRIX_COLS <= 16)
 | 
			
		||||
typedef  uint16_t   matrix_row_t;
 | 
			
		||||
#elif (MATRIX_COLS <= 32)
 | 
			
		||||
typedef  uint32_t   matrix_row_t;
 | 
			
		||||
#else
 | 
			
		||||
#error "MATRIX_COLS: invalid value"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MATRIX_IS_ON(row, col)  (matrix_get_row(row) && (1<<col))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* number of matrix rows */
 | 
			
		||||
uint8_t matrix_rows(void);
 | 
			
		||||
/* number of matrix columns */
 | 
			
		||||
uint8_t matrix_cols(void);
 | 
			
		||||
/* intialize matrix for scaning. should be called once. */
 | 
			
		||||
void matrix_init(void);
 | 
			
		||||
/* scan all key states on matrix */
 | 
			
		||||
uint8_t matrix_scan(void);
 | 
			
		||||
/* whether modified from previous scan. used after matrix_scan. */
 | 
			
		||||
bool matrix_is_modified(void) __attribute__ ((deprecated));
 | 
			
		||||
/* whether a swtich is on */
 | 
			
		||||
bool matrix_is_on(uint8_t row, uint8_t col);
 | 
			
		||||
/* matrix state on row */
 | 
			
		||||
matrix_row_t matrix_get_row(uint8_t row);
 | 
			
		||||
/* print matrix for debug */
 | 
			
		||||
void matrix_print(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* power control */
 | 
			
		||||
void matrix_power_up(void);
 | 
			
		||||
void matrix_power_down(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										4
									
								
								common/mbed/bootloader.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								common/mbed/bootloader.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void bootloader_jump(void) {}
 | 
			
		||||
							
								
								
									
										6
									
								
								common/mbed/suspend.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								common/mbed/suspend.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void suspend_power_down(void) {}
 | 
			
		||||
bool suspend_wakeup_condition(void) { return true; }
 | 
			
		||||
void suspend_wakeup_init(void) {}
 | 
			
		||||
							
								
								
									
										41
									
								
								common/mbed/timer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								common/mbed/timer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
#include "cmsis.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
/* Mill second tick count */
 | 
			
		||||
volatile uint32_t timer_count = 0;
 | 
			
		||||
 | 
			
		||||
/* Timer interrupt handler */
 | 
			
		||||
void SysTick_Handler(void)  {
 | 
			
		||||
    timer_count++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void timer_init(void)
 | 
			
		||||
{
 | 
			
		||||
    timer_count = 0;
 | 
			
		||||
    SysTick_Config(SystemCoreClock / 1000); /* 1ms tick */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void timer_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    timer_count = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t timer_read(void)
 | 
			
		||||
{
 | 
			
		||||
    return (uint16_t)(timer_count & 0xFFFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t timer_read32(void)
 | 
			
		||||
{
 | 
			
		||||
    return timer_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t timer_elapsed(uint16_t last)
 | 
			
		||||
{
 | 
			
		||||
    return TIMER_DIFF_16(timer_read(), last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t timer_elapsed32(uint32_t last)
 | 
			
		||||
{
 | 
			
		||||
    return TIMER_DIFF_32(timer_read32(), last);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								common/mbed/xprintf.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								common/mbed/xprintf.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
#include <cstdarg>
 | 
			
		||||
//#include <stdarg.h>
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "mbed/xprintf.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define STRING_STACK_LIMIT    120
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
int xprintf(const char* format, ...) { return 0; }
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
/* mbed Serial */
 | 
			
		||||
Serial ser(UART_TX, UART_RX);
 | 
			
		||||
 | 
			
		||||
/* TODO: Need small implementation for embedded */
 | 
			
		||||
int xprintf(const char* format, ...)
 | 
			
		||||
{
 | 
			
		||||
    /* copy from mbed/common/RawSerial.cpp */
 | 
			
		||||
    std::va_list arg;
 | 
			
		||||
    va_start(arg, format);
 | 
			
		||||
    int len = vsnprintf(NULL, 0, format, arg);
 | 
			
		||||
    if (len < STRING_STACK_LIMIT) {
 | 
			
		||||
        char temp[STRING_STACK_LIMIT];
 | 
			
		||||
        vsprintf(temp, format, arg);
 | 
			
		||||
        ser.puts(temp);
 | 
			
		||||
    } else {
 | 
			
		||||
        char *temp = new char[len + 1];
 | 
			
		||||
        vsprintf(temp, format, arg);
 | 
			
		||||
        ser.puts(temp);
 | 
			
		||||
        delete[] temp;
 | 
			
		||||
    }
 | 
			
		||||
    va_end(arg);
 | 
			
		||||
    return len;
 | 
			
		||||
 | 
			
		||||
/* Fail: __builtin_va_arg_pack?
 | 
			
		||||
 * https://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Constructing-Calls.html#Constructing-Calls
 | 
			
		||||
    void *arg = __builtin_apply_args();
 | 
			
		||||
    void *ret = __builtin_apply((void*)(&(ser.printf)), arg, 100);
 | 
			
		||||
    __builtin_return(ret)
 | 
			
		||||
*/
 | 
			
		||||
/* Fail: varargs can not be passed to printf
 | 
			
		||||
    //int r = ser.printf("test %i\r\n", 123);
 | 
			
		||||
    va_list arg;
 | 
			
		||||
    va_start(arg, format);
 | 
			
		||||
    int r = ser.printf(format, arg);
 | 
			
		||||
    va_end(arg);
 | 
			
		||||
    return r;
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										17
									
								
								common/mbed/xprintf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								common/mbed/xprintf.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
#ifndef XPRINTF_H
 | 
			
		||||
#define XPRINTF_H
 | 
			
		||||
 | 
			
		||||
//#define xprintf(format, ...)            __xprintf(format, ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int xprintf(const char *format, ...);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										196
									
								
								common/mousekey.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								common/mousekey.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,196 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "mousekey.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static report_mouse_t mouse_report = {};
 | 
			
		||||
static uint8_t mousekey_repeat =  0;
 | 
			
		||||
static uint8_t mousekey_accel = 0;
 | 
			
		||||
 | 
			
		||||
static void mousekey_debug(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Mouse keys  acceleration algorithm
 | 
			
		||||
 *  http://en.wikipedia.org/wiki/Mouse_keys
 | 
			
		||||
 *
 | 
			
		||||
 *  speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
 | 
			
		||||
 */
 | 
			
		||||
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
 | 
			
		||||
uint8_t mk_delay = MOUSEKEY_DELAY/10;
 | 
			
		||||
/* milliseconds between repeated motion events (0-255) */
 | 
			
		||||
uint8_t mk_interval = MOUSEKEY_INTERVAL;
 | 
			
		||||
/* steady speed (in action_delta units) applied each event (0-255) */
 | 
			
		||||
uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
 | 
			
		||||
/* number of events (count) accelerating to steady speed (0-255) */
 | 
			
		||||
uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
 | 
			
		||||
/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
 | 
			
		||||
//int8_t mk_curve = 0;
 | 
			
		||||
/* wheel params */
 | 
			
		||||
uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
 | 
			
		||||
uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint16_t last_timer = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint8_t move_unit(void)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t unit;
 | 
			
		||||
    if (mousekey_accel & (1<<0)) {
 | 
			
		||||
        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
 | 
			
		||||
    } else if (mousekey_accel & (1<<1)) {
 | 
			
		||||
        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
 | 
			
		||||
    } else if (mousekey_accel & (1<<2)) {
 | 
			
		||||
        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
 | 
			
		||||
    } else if (mousekey_repeat == 0) {
 | 
			
		||||
        unit = MOUSEKEY_MOVE_DELTA;
 | 
			
		||||
    } else if (mousekey_repeat >= mk_time_to_max) {
 | 
			
		||||
        unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
 | 
			
		||||
    } else {
 | 
			
		||||
        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
 | 
			
		||||
    }
 | 
			
		||||
    return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t wheel_unit(void)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t unit;
 | 
			
		||||
    if (mousekey_accel & (1<<0)) {
 | 
			
		||||
        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
 | 
			
		||||
    } else if (mousekey_accel & (1<<1)) {
 | 
			
		||||
        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
 | 
			
		||||
    } else if (mousekey_accel & (1<<2)) {
 | 
			
		||||
        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
 | 
			
		||||
    } else if (mousekey_repeat == 0) {
 | 
			
		||||
        unit = MOUSEKEY_WHEEL_DELTA;
 | 
			
		||||
    } else if (mousekey_repeat >= mk_wheel_time_to_max) {
 | 
			
		||||
        unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
 | 
			
		||||
    } else {
 | 
			
		||||
        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
 | 
			
		||||
    }
 | 
			
		||||
    return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_task(void)
 | 
			
		||||
{
 | 
			
		||||
    if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (mousekey_repeat != UINT8_MAX)
 | 
			
		||||
        mousekey_repeat++;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (mouse_report.x > 0) mouse_report.x = move_unit();
 | 
			
		||||
    if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
 | 
			
		||||
    if (mouse_report.y > 0) mouse_report.y = move_unit();
 | 
			
		||||
    if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
 | 
			
		||||
 | 
			
		||||
    /* diagonal move [1/sqrt(2) = 0.7] */
 | 
			
		||||
    if (mouse_report.x && mouse_report.y) {
 | 
			
		||||
        mouse_report.x *= 0.7;
 | 
			
		||||
        mouse_report.y *= 0.7;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mouse_report.v > 0) mouse_report.v = wheel_unit();
 | 
			
		||||
    if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
 | 
			
		||||
    if (mouse_report.h > 0) mouse_report.h = wheel_unit();
 | 
			
		||||
    if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
 | 
			
		||||
 | 
			
		||||
    mousekey_send();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_on(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if      (code == KC_MS_UP)       mouse_report.y = move_unit() * -1;
 | 
			
		||||
    else if (code == KC_MS_DOWN)     mouse_report.y = move_unit();
 | 
			
		||||
    else if (code == KC_MS_LEFT)     mouse_report.x = move_unit() * -1;
 | 
			
		||||
    else if (code == KC_MS_RIGHT)    mouse_report.x = move_unit();
 | 
			
		||||
    else if (code == KC_MS_WH_UP)    mouse_report.v = wheel_unit();
 | 
			
		||||
    else if (code == KC_MS_WH_DOWN)  mouse_report.v = wheel_unit() * -1;
 | 
			
		||||
    else if (code == KC_MS_WH_LEFT)  mouse_report.h = wheel_unit() * -1;
 | 
			
		||||
    else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
 | 
			
		||||
    else if (code == KC_MS_BTN1)     mouse_report.buttons |= MOUSE_BTN1;
 | 
			
		||||
    else if (code == KC_MS_BTN2)     mouse_report.buttons |= MOUSE_BTN2;
 | 
			
		||||
    else if (code == KC_MS_BTN3)     mouse_report.buttons |= MOUSE_BTN3;
 | 
			
		||||
    else if (code == KC_MS_BTN4)     mouse_report.buttons |= MOUSE_BTN4;
 | 
			
		||||
    else if (code == KC_MS_BTN5)     mouse_report.buttons |= MOUSE_BTN5;
 | 
			
		||||
    else if (code == KC_MS_ACCEL0)   mousekey_accel |= (1<<0);
 | 
			
		||||
    else if (code == KC_MS_ACCEL1)   mousekey_accel |= (1<<1);
 | 
			
		||||
    else if (code == KC_MS_ACCEL2)   mousekey_accel |= (1<<2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_off(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if      (code == KC_MS_UP       && mouse_report.y < 0) mouse_report.y = 0;
 | 
			
		||||
    else if (code == KC_MS_DOWN     && mouse_report.y > 0) mouse_report.y = 0;
 | 
			
		||||
    else if (code == KC_MS_LEFT     && mouse_report.x < 0) mouse_report.x = 0;
 | 
			
		||||
    else if (code == KC_MS_RIGHT    && mouse_report.x > 0) mouse_report.x = 0;
 | 
			
		||||
    else if (code == KC_MS_WH_UP    && mouse_report.v > 0) mouse_report.v = 0;
 | 
			
		||||
    else if (code == KC_MS_WH_DOWN  && mouse_report.v < 0) mouse_report.v = 0;
 | 
			
		||||
    else if (code == KC_MS_WH_LEFT  && mouse_report.h < 0) mouse_report.h = 0;
 | 
			
		||||
    else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
 | 
			
		||||
    else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
 | 
			
		||||
    else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
 | 
			
		||||
    else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
 | 
			
		||||
    else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
 | 
			
		||||
    else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
 | 
			
		||||
    else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
 | 
			
		||||
    else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
 | 
			
		||||
    else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
 | 
			
		||||
 | 
			
		||||
    if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
 | 
			
		||||
        mousekey_repeat = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_send(void)
 | 
			
		||||
{
 | 
			
		||||
    mousekey_debug();
 | 
			
		||||
    host_mouse_send(&mouse_report);
 | 
			
		||||
    last_timer = timer_read();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    mouse_report = (report_mouse_t){};
 | 
			
		||||
    mousekey_repeat = 0;
 | 
			
		||||
    mousekey_accel = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mousekey_debug(void)
 | 
			
		||||
{
 | 
			
		||||
    if (!debug_mouse) return;
 | 
			
		||||
    print("mousekey [btn|x y v h](rep/acl): [");
 | 
			
		||||
    phex(mouse_report.buttons); print("|");
 | 
			
		||||
    print_decs(mouse_report.x); print(" ");
 | 
			
		||||
    print_decs(mouse_report.y); print(" ");
 | 
			
		||||
    print_decs(mouse_report.v); print(" ");
 | 
			
		||||
    print_decs(mouse_report.h); print("](");
 | 
			
		||||
    print_dec(mousekey_repeat); print("/");
 | 
			
		||||
    print_dec(mousekey_accel); print(")\n");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								common/mousekey.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								common/mousekey.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef MOUSEKEY_H
 | 
			
		||||
#define  MOUSEKEY_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "host.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* max value on report descriptor */
 | 
			
		||||
#define MOUSEKEY_MOVE_MAX       127
 | 
			
		||||
#define MOUSEKEY_WHEEL_MAX      127
 | 
			
		||||
 | 
			
		||||
#ifndef MOUSEKEY_MOVE_DELTA
 | 
			
		||||
#define MOUSEKEY_MOVE_DELTA     5
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_WHEEL_DELTA
 | 
			
		||||
#define MOUSEKEY_WHEEL_DELTA    1
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_DELAY
 | 
			
		||||
#define MOUSEKEY_DELAY 300
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_INTERVAL
 | 
			
		||||
#define MOUSEKEY_INTERVAL 50
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_MAX_SPEED
 | 
			
		||||
#define MOUSEKEY_MAX_SPEED 10
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_TIME_TO_MAX
 | 
			
		||||
#define MOUSEKEY_TIME_TO_MAX 20
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_WHEEL_MAX_SPEED
 | 
			
		||||
#define MOUSEKEY_WHEEL_MAX_SPEED 8
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
 | 
			
		||||
#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern uint8_t mk_delay;
 | 
			
		||||
extern uint8_t mk_interval;
 | 
			
		||||
extern uint8_t mk_max_speed;
 | 
			
		||||
extern uint8_t mk_time_to_max;
 | 
			
		||||
extern uint8_t mk_wheel_max_speed;
 | 
			
		||||
extern uint8_t mk_wheel_time_to_max;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void mousekey_task(void);
 | 
			
		||||
void mousekey_on(uint8_t code);
 | 
			
		||||
void mousekey_off(uint8_t code);
 | 
			
		||||
void mousekey_clear(void);
 | 
			
		||||
void mousekey_send(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										25
									
								
								common/nodebug.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								common/nodebug.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef NODEBUG_H
 | 
			
		||||
#define NODEBUG_H 1
 | 
			
		||||
 | 
			
		||||
#define NO_DEBUG
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#undef NO_DEBUG
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										48
									
								
								common/print.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								common/print.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
 | 
			
		||||
/* Very basic print functions, intended to be used with usb_debug_only.c
 | 
			
		||||
 * http://www.pjrc.com/teensy/
 | 
			
		||||
 * Copyright (c) 2008 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:
 | 
			
		||||
 * 
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "print.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_PRINT
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
 | 
			
		||||
#define sendchar(c)    xputc(c)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
 | 
			
		||||
{
 | 
			
		||||
    xdev_out(sendchar_func);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__arm__)
 | 
			
		||||
 | 
			
		||||
// TODO
 | 
			
		||||
//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										137
									
								
								common/print.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								common/print.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,137 @@
 | 
			
		|||
/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
 | 
			
		||||
/* Very basic print functions, intended to be used with usb_debug_only.c
 | 
			
		||||
 * http://www.pjrc.com/teensy/
 | 
			
		||||
 * Copyright (c) 2008 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:
 | 
			
		||||
 * 
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PRINT_H__
 | 
			
		||||
#define PRINT_H__ 1
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef NO_PRINT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
 | 
			
		||||
#include "avr/xprintf.h"
 | 
			
		||||
#define print(s)    xputs(PSTR(s))
 | 
			
		||||
#define println(s)  xputs(PSTR(s "\r\n"))
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
/* function pointer of sendchar to be used by print utility */
 | 
			
		||||
void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
 | 
			
		||||
 | 
			
		||||
#elif defined(__arm__)
 | 
			
		||||
 | 
			
		||||
#include "mbed/xprintf.h"
 | 
			
		||||
 | 
			
		||||
#define print(s)    xprintf(s)
 | 
			
		||||
#define println(s)  xprintf(s "\r\n")
 | 
			
		||||
 | 
			
		||||
/* TODO: to select output destinations: UART/USBSerial */
 | 
			
		||||
#define print_set_sendchar(func)
 | 
			
		||||
 | 
			
		||||
#endif /* __AVR__ */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* decimal */
 | 
			
		||||
#define print_dec(i)                xprintf("%u", i)
 | 
			
		||||
#define print_decs(i)               xprintf("%d", i)
 | 
			
		||||
/* hex */
 | 
			
		||||
#define print_hex4(i)               xprintf("%X", i)
 | 
			
		||||
#define print_hex8(i)               xprintf("%02X", i)
 | 
			
		||||
#define print_hex16(i)              xprintf("%04X", i)
 | 
			
		||||
#define print_hex32(i)              xprintf("%08lX", i)
 | 
			
		||||
/* binary */
 | 
			
		||||
#define print_bin4(i)               xprintf("%04b", i)
 | 
			
		||||
#define print_bin8(i)               xprintf("%08b", i)
 | 
			
		||||
#define print_bin16(i)              xprintf("%016b", i)
 | 
			
		||||
#define print_bin32(i)              xprintf("%032lb", i)
 | 
			
		||||
#define print_bin_reverse8(i)       xprintf("%08b", bitrev(i))
 | 
			
		||||
#define print_bin_reverse16(i)      xprintf("%016b", bitrev16(i))
 | 
			
		||||
#define print_bin_reverse32(i)      xprintf("%032lb", bitrev32(i))
 | 
			
		||||
/* print value utility */
 | 
			
		||||
#define print_val_dec(v)            xprintf(#v ": %u\n", v)
 | 
			
		||||
#define print_val_decs(v)           xprintf(#v ": %d\n", v)
 | 
			
		||||
#define print_val_hex8(v)           xprintf(#v ": %X\n", v)
 | 
			
		||||
#define print_val_hex16(v)          xprintf(#v ": %02X\n", v)
 | 
			
		||||
#define print_val_hex32(v)          xprintf(#v ": %04lX\n", v)
 | 
			
		||||
#define print_val_bin8(v)           xprintf(#v ": %08b\n", v)
 | 
			
		||||
#define print_val_bin16(v)          xprintf(#v ": %016b\n", v)
 | 
			
		||||
#define print_val_bin32(v)          xprintf(#v ": %032lb\n", v)
 | 
			
		||||
#define print_val_bin_reverse8(v)   xprintf(#v ": %08b\n", bitrev(v))
 | 
			
		||||
#define print_val_bin_reverse16(v)  xprintf(#v ": %016b\n", bitrev16(v))
 | 
			
		||||
#define print_val_bin_reverse32(v)  xprintf(#v ": %032lb\n", bitrev32(v))
 | 
			
		||||
 | 
			
		||||
#else   /* NO_PRINT */
 | 
			
		||||
 | 
			
		||||
#define xprintf
 | 
			
		||||
#define print
 | 
			
		||||
#define println
 | 
			
		||||
#define print_set_sendchar(func)
 | 
			
		||||
#define print_dec(data)
 | 
			
		||||
#define print_decs(data)
 | 
			
		||||
#define print_hex4(data)
 | 
			
		||||
#define print_hex8(data)
 | 
			
		||||
#define print_hex16(data)
 | 
			
		||||
#define print_hex32(data)
 | 
			
		||||
#define print_bin4(data)
 | 
			
		||||
#define print_bin8(data)
 | 
			
		||||
#define print_bin16(data)
 | 
			
		||||
#define print_bin32(data)
 | 
			
		||||
#define print_bin_reverse8(data)
 | 
			
		||||
#define print_bin_reverse16(data)
 | 
			
		||||
#define print_bin_reverse32(data)
 | 
			
		||||
#define print_val_dec(v)
 | 
			
		||||
#define print_val_decs(v)
 | 
			
		||||
#define print_val_hex8(v)
 | 
			
		||||
#define print_val_hex16(v)
 | 
			
		||||
#define print_val_hex32(v)
 | 
			
		||||
#define print_val_bin8(v)
 | 
			
		||||
#define print_val_bin16(v)
 | 
			
		||||
#define print_val_bin32(v)
 | 
			
		||||
#define print_val_bin_reverse8(v)
 | 
			
		||||
#define print_val_bin_reverse16(v)
 | 
			
		||||
#define print_val_bin_reverse32(v)
 | 
			
		||||
 | 
			
		||||
#endif  /* NO_PRINT */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Backward compatiblitly for old name */
 | 
			
		||||
#define pdec(data)              print_dec(data)
 | 
			
		||||
#define pdec16(data)            print_dec(data)
 | 
			
		||||
#define phex(data)              print_hex8(data)
 | 
			
		||||
#define phex16(data)            print_hex16(data)
 | 
			
		||||
#define pbin(data)              print_bin8(data)
 | 
			
		||||
#define pbin16(data)            print_bin16(data)
 | 
			
		||||
#define pbin_reverse(data)      print_bin_reverse8(data)
 | 
			
		||||
#define pbin_reverse16(data)    print_bin_reverse16(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										12
									
								
								common/progmem.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								common/progmem.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
#ifndef PROGMEM_H
 | 
			
		||||
#define PROGMEM_H 1
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#   include <avr/pgmspace.h>
 | 
			
		||||
#elif defined(__arm__)
 | 
			
		||||
#   define PROGMEM
 | 
			
		||||
#   define pgm_read_byte(p)     *(p)
 | 
			
		||||
#   define pgm_read_word(p)     *(p)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										183
									
								
								common/report.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								common/report.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,183 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef REPORT_H
 | 
			
		||||
#define REPORT_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* report id */
 | 
			
		||||
#define REPORT_ID_MOUSE     1
 | 
			
		||||
#define REPORT_ID_SYSTEM    2
 | 
			
		||||
#define REPORT_ID_CONSUMER  3
 | 
			
		||||
 | 
			
		||||
/* mouse buttons */
 | 
			
		||||
#define MOUSE_BTN1 (1<<0)
 | 
			
		||||
#define MOUSE_BTN2 (1<<1)
 | 
			
		||||
#define MOUSE_BTN3 (1<<2)
 | 
			
		||||
#define MOUSE_BTN4 (1<<3)
 | 
			
		||||
#define MOUSE_BTN5 (1<<4)
 | 
			
		||||
 | 
			
		||||
/* Consumer Page(0x0C)
 | 
			
		||||
 * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
 | 
			
		||||
 */
 | 
			
		||||
#define AUDIO_MUTE              0x00E2
 | 
			
		||||
#define AUDIO_VOL_UP            0x00E9
 | 
			
		||||
#define AUDIO_VOL_DOWN          0x00EA
 | 
			
		||||
#define TRANSPORT_NEXT_TRACK    0x00B5
 | 
			
		||||
#define TRANSPORT_PREV_TRACK    0x00B6
 | 
			
		||||
#define TRANSPORT_STOP          0x00B7
 | 
			
		||||
#define TRANSPORT_STOP_EJECT    0x00CC
 | 
			
		||||
#define TRANSPORT_PLAY_PAUSE    0x00CD
 | 
			
		||||
/* application launch */
 | 
			
		||||
#define AL_CC_CONFIG            0x0183
 | 
			
		||||
#define AL_EMAIL                0x018A
 | 
			
		||||
#define AL_CALCULATOR           0x0192
 | 
			
		||||
#define AL_LOCAL_BROWSER        0x0194
 | 
			
		||||
/* application control */
 | 
			
		||||
#define AC_SEARCH               0x0221
 | 
			
		||||
#define AC_HOME                 0x0223
 | 
			
		||||
#define AC_BACK                 0x0224
 | 
			
		||||
#define AC_FORWARD              0x0225
 | 
			
		||||
#define AC_STOP                 0x0226
 | 
			
		||||
#define AC_REFRESH              0x0227
 | 
			
		||||
#define AC_BOOKMARKS            0x022A
 | 
			
		||||
/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
 | 
			
		||||
#define AL_LOCK                 0x019E
 | 
			
		||||
#define TRANSPORT_RECORD        0x00B2
 | 
			
		||||
#define TRANSPORT_FAST_FORWARD  0x00B3
 | 
			
		||||
#define TRANSPORT_REWIND        0x00B4
 | 
			
		||||
#define TRANSPORT_EJECT         0x00B8
 | 
			
		||||
#define AC_MINIMIZE             0x0206
 | 
			
		||||
 | 
			
		||||
/* Generic Desktop Page(0x01) - system power control */
 | 
			
		||||
#define SYSTEM_POWER_DOWN       0x0081
 | 
			
		||||
#define SYSTEM_SLEEP            0x0082
 | 
			
		||||
#define SYSTEM_WAKE_UP          0x0083
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* key report size(NKRO or boot mode) */
 | 
			
		||||
#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
 | 
			
		||||
#   include "usb.h"
 | 
			
		||||
#   define KEYBOARD_REPORT_SIZE KBD2_SIZE
 | 
			
		||||
#   define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
 | 
			
		||||
#   define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
 | 
			
		||||
 | 
			
		||||
#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
 | 
			
		||||
#   include "protocol/lufa/descriptor.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
 | 
			
		||||
#   define KEYBOARD_REPORT_KEYS 6
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys.
 | 
			
		||||
 *
 | 
			
		||||
 * byte |0       |1       |2       |3       |4       |5       |6       |7
 | 
			
		||||
 * -----+--------+--------+--------+--------+--------+--------+--------+--------
 | 
			
		||||
 * desc |mods    |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5]
 | 
			
		||||
 *
 | 
			
		||||
 * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode.
 | 
			
		||||
 *
 | 
			
		||||
 * byte |0       |1       |2       |3       |4       |5       |6       |7        ... |15
 | 
			
		||||
 * -----+--------+--------+--------+--------+--------+--------+--------+--------     +--------
 | 
			
		||||
 * desc |mods    |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6]  ... |bit[14]
 | 
			
		||||
 *
 | 
			
		||||
 * mods retains state of 8 modifiers.
 | 
			
		||||
 *
 | 
			
		||||
 *  bit |0       |1       |2       |3       |4       |5       |6       |7
 | 
			
		||||
 * -----+--------+--------+--------+--------+--------+--------+--------+--------
 | 
			
		||||
 * desc |Lcontrol|Lshift  |Lalt    |Lgui    |Rcontrol|Rshift  |Ralt    |Rgui
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint8_t raw[KEYBOARD_REPORT_SIZE];
 | 
			
		||||
    struct {
 | 
			
		||||
        uint8_t mods;
 | 
			
		||||
        uint8_t reserved;
 | 
			
		||||
        uint8_t keys[KEYBOARD_REPORT_KEYS];
 | 
			
		||||
    };
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    struct {
 | 
			
		||||
        uint8_t mods;
 | 
			
		||||
        uint8_t bits[KEYBOARD_REPORT_BITS];
 | 
			
		||||
    } nkro;
 | 
			
		||||
#endif
 | 
			
		||||
} __attribute__ ((packed)) report_keyboard_t;
 | 
			
		||||
/*
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t mods;
 | 
			
		||||
    uint8_t reserved;
 | 
			
		||||
    uint8_t keys[REPORT_KEYS];
 | 
			
		||||
} __attribute__ ((packed)) report_keyboard_t;
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t buttons;
 | 
			
		||||
    int8_t x;
 | 
			
		||||
    int8_t y;
 | 
			
		||||
    int8_t v;
 | 
			
		||||
    int8_t h;
 | 
			
		||||
} __attribute__ ((packed)) report_mouse_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* keycode to system usage */
 | 
			
		||||
#define KEYCODE2SYSTEM(key) \
 | 
			
		||||
    (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \
 | 
			
		||||
    (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \
 | 
			
		||||
    (key == KC_SYSTEM_WAKE  ? SYSTEM_WAKE_UP : 0)))
 | 
			
		||||
 | 
			
		||||
/* keycode to consumer usage */
 | 
			
		||||
#define KEYCODE2CONSUMER(key) \
 | 
			
		||||
    (key == KC_AUDIO_MUTE       ?  AUDIO_MUTE : \
 | 
			
		||||
    (key == KC_AUDIO_VOL_UP     ?  AUDIO_VOL_UP : \
 | 
			
		||||
    (key == KC_AUDIO_VOL_DOWN   ?  AUDIO_VOL_DOWN : \
 | 
			
		||||
    (key == KC_MEDIA_NEXT_TRACK ?  TRANSPORT_NEXT_TRACK : \
 | 
			
		||||
    (key == KC_MEDIA_PREV_TRACK ?  TRANSPORT_PREV_TRACK : \
 | 
			
		||||
    (key == KC_MEDIA_FAST_FORWARD ?  TRANSPORT_FAST_FORWARD : \
 | 
			
		||||
    (key == KC_MEDIA_REWIND     ?  TRANSPORT_REWIND : \
 | 
			
		||||
    (key == KC_MEDIA_STOP       ?  TRANSPORT_STOP : \
 | 
			
		||||
    (key == KC_MEDIA_EJECT      ?  TRANSPORT_STOP_EJECT : \
 | 
			
		||||
    (key == KC_MEDIA_PLAY_PAUSE ?  TRANSPORT_PLAY_PAUSE : \
 | 
			
		||||
    (key == KC_MEDIA_SELECT     ?  AL_CC_CONFIG : \
 | 
			
		||||
    (key == KC_MAIL             ?  AL_EMAIL : \
 | 
			
		||||
    (key == KC_CALCULATOR       ?  AL_CALCULATOR : \
 | 
			
		||||
    (key == KC_MY_COMPUTER      ?  AL_LOCAL_BROWSER : \
 | 
			
		||||
    (key == KC_WWW_SEARCH       ?  AC_SEARCH : \
 | 
			
		||||
    (key == KC_WWW_HOME         ?  AC_HOME : \
 | 
			
		||||
    (key == KC_WWW_BACK         ?  AC_BACK : \
 | 
			
		||||
    (key == KC_WWW_FORWARD      ?  AC_FORWARD : \
 | 
			
		||||
    (key == KC_WWW_STOP         ?  AC_STOP : \
 | 
			
		||||
    (key == KC_WWW_REFRESH      ?  AC_REFRESH : \
 | 
			
		||||
    (key == KC_WWW_FAVORITES    ?  AC_BOOKMARKS : 0)))))))))))))))))))))
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										35
									
								
								common/sendchar.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								common/sendchar.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef SENDCHAR_H
 | 
			
		||||
#define SENDCHAR_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* transmit a character.  return 0 on success, -1 on error. */
 | 
			
		||||
int8_t sendchar(uint8_t c);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								common/sendchar_null.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								common/sendchar_null.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "sendchar.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int8_t sendchar(uint8_t c)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								common/sendchar_uart.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								common/sendchar_uart.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
#include "sendchar.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int8_t sendchar(uint8_t c)
 | 
			
		||||
{
 | 
			
		||||
    uart_putchar(c);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								common/sleep_led.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								common/sleep_led.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,95 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <avr/pgmspace.h>
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "sleep_led.h"
 | 
			
		||||
 | 
			
		||||
/* Software PWM
 | 
			
		||||
 *  ______           ______           __
 | 
			
		||||
 * |  ON  |___OFF___|  ON  |___OFF___|   ....
 | 
			
		||||
 * |<-------------->|<-------------->|<- ....
 | 
			
		||||
 *     PWM period       PWM period
 | 
			
		||||
 *
 | 
			
		||||
 * 256              interrupts/period[resolution]
 | 
			
		||||
 * 64               periods/second[frequency]
 | 
			
		||||
 * 256*64           interrupts/second
 | 
			
		||||
 * F_CPU/(256*64)   clocks/interrupt
 | 
			
		||||
 */
 | 
			
		||||
#define SLEEP_LED_TIMER_TOP F_CPU/(256*64)
 | 
			
		||||
 | 
			
		||||
void sleep_led_init(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Timer1 setup */
 | 
			
		||||
    /* CTC mode */
 | 
			
		||||
    TCCR1B |= _BV(WGM12);
 | 
			
		||||
    /* Clock selelct: clk/1 */
 | 
			
		||||
    TCCR1B |= _BV(CS10);
 | 
			
		||||
    /* Set TOP value */
 | 
			
		||||
    uint8_t sreg = SREG;
 | 
			
		||||
    cli();
 | 
			
		||||
    OCR1AH = (SLEEP_LED_TIMER_TOP>>8)&0xff;
 | 
			
		||||
    OCR1AL = SLEEP_LED_TIMER_TOP&0xff;
 | 
			
		||||
    SREG = sreg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sleep_led_enable(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Enable Compare Match Interrupt */
 | 
			
		||||
    TIMSK1 |= _BV(OCIE1A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sleep_led_disable(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Disable Compare Match Interrupt */
 | 
			
		||||
    TIMSK1 &= ~_BV(OCIE1A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sleep_led_toggle(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Disable Compare Match Interrupt */
 | 
			
		||||
    TIMSK1 ^= _BV(OCIE1A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 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] PROGMEM = {
 | 
			
		||||
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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect)
 | 
			
		||||
{
 | 
			
		||||
    /* Software PWM
 | 
			
		||||
     * timer:1111 1111 1111 1111
 | 
			
		||||
     *       \_____/\/ \_______/____  count(0-255)
 | 
			
		||||
     *          \    \______________  duration of step(4)
 | 
			
		||||
     *           \__________________  index of step table(0-63)
 | 
			
		||||
     */
 | 
			
		||||
    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 == pgm_read_byte(&breathing_table[timer.pwm.index])) {
 | 
			
		||||
        led_set(0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								common/sleep_led.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								common/sleep_led.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
#ifndef SLEEP_LED_H
 | 
			
		||||
#define SLEEP_LED_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef SLEEP_LED_ENABLE
 | 
			
		||||
 | 
			
		||||
void sleep_led_init(void);
 | 
			
		||||
void sleep_led_enable(void);
 | 
			
		||||
void sleep_led_disable(void);
 | 
			
		||||
void sleep_led_toggle(void);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define sleep_led_init()
 | 
			
		||||
#define sleep_led_enable()
 | 
			
		||||
#define sleep_led_disable()
 | 
			
		||||
#define sleep_led_toggle()
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										13
									
								
								common/suspend.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								common/suspend.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
#ifndef SUSPEND_H
 | 
			
		||||
#define SUSPEND_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void suspend_idle(uint8_t timeout);
 | 
			
		||||
void suspend_power_down(void);
 | 
			
		||||
bool suspend_wakeup_condition(void);
 | 
			
		||||
void suspend_wakeup_init(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										53
									
								
								common/timer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								common/timer.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef TIMER_H
 | 
			
		||||
#define TIMER_H 1
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#include "avr/timer_avr.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define TIMER_DIFF(a, b, max)   ((a) >= (b) ?  (a) - (b) : (max) - (b) + (a))
 | 
			
		||||
#define TIMER_DIFF_8(a, b)      TIMER_DIFF(a, b, UINT8_MAX)
 | 
			
		||||
#define TIMER_DIFF_16(a, b)     TIMER_DIFF(a, b, UINT16_MAX)
 | 
			
		||||
#define TIMER_DIFF_32(a, b)     TIMER_DIFF(a, b, UINT32_MAX)
 | 
			
		||||
#define TIMER_DIFF_RAW(a, b)    TIMER_DIFF_8(a, b)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern volatile uint32_t timer_count;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void timer_init(void);
 | 
			
		||||
void timer_clear(void);
 | 
			
		||||
uint16_t timer_read(void);
 | 
			
		||||
uint32_t timer_read32(void);
 | 
			
		||||
uint16_t timer_elapsed(uint16_t last);
 | 
			
		||||
uint32_t timer_elapsed32(uint32_t last);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										129
									
								
								common/uart.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								common/uart.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
// TODO: Teensy support(ATMega32u4/AT90USB128)
 | 
			
		||||
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
 | 
			
		||||
/* UART Example for Teensy USB Development Board
 | 
			
		||||
 * http://www.pjrc.com/teensy/
 | 
			
		||||
 * Copyright (c) 2009 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:
 | 
			
		||||
 * 
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Version 1.0: Initial Release
 | 
			
		||||
// Version 1.1: Add support for Teensy 2.0, minor optimizations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
 | 
			
		||||
// These buffers may be any size from 2 to 256 bytes.
 | 
			
		||||
#define RX_BUFFER_SIZE 64
 | 
			
		||||
#define TX_BUFFER_SIZE 40
 | 
			
		||||
 | 
			
		||||
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
 | 
			
		||||
static volatile uint8_t tx_buffer_head;
 | 
			
		||||
static volatile uint8_t tx_buffer_tail;
 | 
			
		||||
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
 | 
			
		||||
static volatile uint8_t rx_buffer_head;
 | 
			
		||||
static volatile uint8_t rx_buffer_tail;
 | 
			
		||||
 | 
			
		||||
// Initialize the UART
 | 
			
		||||
void uart_init(uint32_t baud)
 | 
			
		||||
{
 | 
			
		||||
	cli();
 | 
			
		||||
	UBRR0 = (F_CPU / 4 / baud - 1) / 2;
 | 
			
		||||
	UCSR0A = (1<<U2X0);
 | 
			
		||||
	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
 | 
			
		||||
	UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
 | 
			
		||||
	tx_buffer_head = tx_buffer_tail = 0;
 | 
			
		||||
	rx_buffer_head = rx_buffer_tail = 0;
 | 
			
		||||
	sei();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Transmit a byte
 | 
			
		||||
void uart_putchar(uint8_t c)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t i;
 | 
			
		||||
 | 
			
		||||
	i = tx_buffer_head + 1;
 | 
			
		||||
	if (i >= TX_BUFFER_SIZE) i = 0;
 | 
			
		||||
	while (tx_buffer_tail == i) ; // wait until space in buffer
 | 
			
		||||
	//cli();
 | 
			
		||||
	tx_buffer[i] = c;
 | 
			
		||||
	tx_buffer_head = i;
 | 
			
		||||
	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
 | 
			
		||||
	//sei();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Receive a byte
 | 
			
		||||
uint8_t uart_getchar(void)
 | 
			
		||||
{
 | 
			
		||||
        uint8_t c, i;
 | 
			
		||||
 | 
			
		||||
	while (rx_buffer_head == rx_buffer_tail) ; // wait for character
 | 
			
		||||
        i = rx_buffer_tail + 1;
 | 
			
		||||
        if (i >= RX_BUFFER_SIZE) i = 0;
 | 
			
		||||
        c = rx_buffer[i];
 | 
			
		||||
        rx_buffer_tail = i;
 | 
			
		||||
        return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return the number of bytes waiting in the receive buffer.
 | 
			
		||||
// Call this before uart_getchar() to check if it will need
 | 
			
		||||
// to wait for a byte to arrive.
 | 
			
		||||
uint8_t uart_available(void)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t head, tail;
 | 
			
		||||
 | 
			
		||||
	head = rx_buffer_head;
 | 
			
		||||
	tail = rx_buffer_tail;
 | 
			
		||||
	if (head >= tail) return head - tail;
 | 
			
		||||
	return RX_BUFFER_SIZE + head - tail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Transmit Interrupt
 | 
			
		||||
ISR(USART_UDRE_vect)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t i;
 | 
			
		||||
 | 
			
		||||
	if (tx_buffer_head == tx_buffer_tail) {
 | 
			
		||||
		// buffer is empty, disable transmit interrupt
 | 
			
		||||
		UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
 | 
			
		||||
	} else {
 | 
			
		||||
		i = tx_buffer_tail + 1;
 | 
			
		||||
		if (i >= TX_BUFFER_SIZE) i = 0;
 | 
			
		||||
		UDR0 = tx_buffer[i];
 | 
			
		||||
		tx_buffer_tail = i;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Receive Interrupt
 | 
			
		||||
ISR(USART_RX_vect)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t c, i;
 | 
			
		||||
 | 
			
		||||
	c = UDR0;
 | 
			
		||||
	i = rx_buffer_head + 1;
 | 
			
		||||
	if (i >= RX_BUFFER_SIZE) i = 0;
 | 
			
		||||
	if (i != rx_buffer_tail) {
 | 
			
		||||
		rx_buffer[i] = c;
 | 
			
		||||
		rx_buffer_head = i;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								common/uart.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								common/uart.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
#ifndef _uart_included_h_
 | 
			
		||||
#define _uart_included_h_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void uart_init(uint32_t baud);
 | 
			
		||||
void uart_putchar(uint8_t c);
 | 
			
		||||
uint8_t uart_getchar(void);
 | 
			
		||||
uint8_t uart_available(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										101
									
								
								common/util.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								common/util.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
// bit population - return number of on-bit
 | 
			
		||||
uint8_t bitpop(uint8_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t c;
 | 
			
		||||
    for (c = 0; bits; c++)
 | 
			
		||||
        bits &= bits - 1;
 | 
			
		||||
    return c;
 | 
			
		||||
/*
 | 
			
		||||
    const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
 | 
			
		||||
    return bit_count[bits>>4] + bit_count[bits&0x0F]
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t bitpop16(uint16_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t c;
 | 
			
		||||
    for (c = 0; bits; c++)
 | 
			
		||||
        bits &= bits - 1;
 | 
			
		||||
    return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t bitpop32(uint32_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t c;
 | 
			
		||||
    for (c = 0; bits; c++)
 | 
			
		||||
        bits &= bits - 1;
 | 
			
		||||
    return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// most significant on-bit - return highest location of on-bit
 | 
			
		||||
// NOTE: return 0 when bit0 is on or all bits are off
 | 
			
		||||
uint8_t biton(uint8_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t n = 0;
 | 
			
		||||
    if (bits >> 4) { bits >>= 4; n += 4;}
 | 
			
		||||
    if (bits >> 2) { bits >>= 2; n += 2;}
 | 
			
		||||
    if (bits >> 1) { bits >>= 1; n += 1;}
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t biton16(uint16_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t n = 0;
 | 
			
		||||
    if (bits >> 8) { bits >>= 8; n += 8;}
 | 
			
		||||
    if (bits >> 4) { bits >>= 4; n += 4;}
 | 
			
		||||
    if (bits >> 2) { bits >>= 2; n += 2;}
 | 
			
		||||
    if (bits >> 1) { bits >>= 1; n += 1;}
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t biton32(uint32_t bits)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t n = 0;
 | 
			
		||||
    if (bits >>16) { bits >>=16; n +=16;}
 | 
			
		||||
    if (bits >> 8) { bits >>= 8; n += 8;}
 | 
			
		||||
    if (bits >> 4) { bits >>= 4; n += 4;}
 | 
			
		||||
    if (bits >> 2) { bits >>= 2; n += 2;}
 | 
			
		||||
    if (bits >> 1) { bits >>= 1; n += 1;}
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t bitrev(uint8_t bits)
 | 
			
		||||
{
 | 
			
		||||
    bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4;
 | 
			
		||||
    bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2;
 | 
			
		||||
    bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1;
 | 
			
		||||
    return bits;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t bitrev16(uint16_t bits)
 | 
			
		||||
{
 | 
			
		||||
    bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8);
 | 
			
		||||
    return bits;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t bitrev32(uint32_t bits)
 | 
			
		||||
{
 | 
			
		||||
    bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16);
 | 
			
		||||
    return bits;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								common/util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								common/util.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef UTIL_H
 | 
			
		||||
#define UTIL_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
// convert to L string
 | 
			
		||||
#define LSTR(s) XLSTR(s)
 | 
			
		||||
#define XLSTR(s) L ## #s
 | 
			
		||||
// convert to string
 | 
			
		||||
#define STR(s) XSTR(s)
 | 
			
		||||
#define XSTR(s) #s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t bitpop(uint8_t bits);
 | 
			
		||||
uint8_t bitpop16(uint16_t bits);
 | 
			
		||||
uint8_t bitpop32(uint32_t bits);
 | 
			
		||||
 | 
			
		||||
uint8_t biton(uint8_t bits);
 | 
			
		||||
uint8_t biton16(uint16_t bits);
 | 
			
		||||
uint8_t biton32(uint32_t bits);
 | 
			
		||||
 | 
			
		||||
uint8_t  bitrev(uint8_t bits);
 | 
			
		||||
uint16_t bitrev16(uint16_t bits);
 | 
			
		||||
uint32_t bitrev32(uint32_t bits);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										20
									
								
								common/wait.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								common/wait.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
#ifndef WAIT_H
 | 
			
		||||
#define WAIT_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#   include <util/delay.h>
 | 
			
		||||
#   define wait_ms(ms)  _delay_ms(ms)
 | 
			
		||||
#   define wait_us(us)  _delay_us(us)
 | 
			
		||||
#elif defined(__arm__)
 | 
			
		||||
#   include "wait_api.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue