/* ---------------------------------------------------------------------------- * main() * ---------------------------------------------------------------------------- * Copyright (c) 2012 Ben Blazak * Released under The MIT License (MIT) (see "license.md") * Project located at * ------------------------------------------------------------------------- */ #include #include // -------------------------------------------------------------------- // types and forward declarations // -------------------------------------------------------------------- typedef int8_t i8; typedef uint8_t u8; typedef int16_t i16; typedef uint16_t u16; typedef uint32_t u32; typedef u8 keycode; typedef u16 media_keycode; typedef u8 layer; typedef u32 millis; // wraps every 50 days, but that's fine for our logic typedef void (*keyfunc)(keycode, bool); #include "./main.h" // -------------------------------------------------------------------- // hardware // -------------------------------------------------------------------- // comment out this define to disable the debug interface completely // however, just not using the functions gets rid of most of the firmware bloat already #define KBD_DEBUG #include "./keyboard/controller.c" #include "./keyboard/keyboard.h" // ---------------------------------------------------------------------------- // layout data // ---------------------------------------------------------------------------- #include "./keyboard/layout.c" // defines: // #define KB_LAYERS #{Layers.size} // static const keycode PROGMEM _kb_layout_code[KB_ROWS][KB_COLUMNS][KB_LAYERS]; // static const keyfunc PROGMEM _kb_layout_func[KB_ROWS][KB_COLUMNS][KB_LAYERS]; /* static u8 layers[KB_LAYERS] = {0, 1, 1+2, 3, 4, 2+3+4}; */ #if KB_LAYERS > 8 #error "can only handle 8 layers for now" #endif // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS]; static bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed; static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS]; static bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed; static layer layers_pressed[KB_ROWS][KB_COLUMNS]; static i8 layers_active[KB_LAYERS]; static layer layers_top; static u8 layers_state; static bool layer_sticky_on; static bool layer_sticky[KB_LAYERS]; static bool layer_sticky_done; static u8 mod_sticky; static bool mod_sticky_done; static millis time_pressed[KB_ROWS][KB_COLUMNS]; // TODO this only exists as a workaround until we handle our own key repeats static const keyfunc _kb_layer_funcs[] = { &kbfun_layer_press_release, &kbfun_layer_sticky, &kbfun_shift_layer_press_release, &kbfun_control_layer_press_release, &kbfun_alt_layer_press_release, &kbfun_win_layer_press_release, }; // ---------------------------------------------------------------------------- // utilities // ---------------------------------------------------------------------------- #define array_length(x) (sizeof(x) / sizeof((x)[0])) #define set_bit(x, i) (x) |= (1u << (i)) #define unset_bit(x, i) (x) &= ~(1u << (i)) #define toggle_bit(x, i) (x) ^= (1u << (i)) #define is_set(x, i) (((x) >> (i)) & 1u) #define is_unset(x, i) !is_set((x), (i)) #define set_layer(x, layer) set_bit((x), (layer) - 1) #define unset_layer(x, layer) unset_bit((x), (layer) - 1) #define toggle_layer(x, layer) toggle_bit((x), (layer) - 1) millis now() { return timer0_ms; } // ---------------------------------------------------------------------------- // main // ---------------------------------------------------------------------------- int main() { // initialize init_hw(); init_layers(); init_sticky(); init_timer(); // never return main_key_loop(); return 0; } void main_key_loop() { for (;;) { // swap `kb_is_pressed` and `kb_was_pressed`, then update bool (*temp)[KB_ROWS][KB_COLUMNS] = kb_was_pressed; kb_was_pressed = kb_is_pressed; kb_is_pressed = temp; kb_update_matrix(*kb_is_pressed); // - execute key functions when their key changes state // - keep track of which layers the keys were on when they were pressed // (so they can be released using the function from that layer) for (u8 row=0; row 0; l--) { if (layers_active[l] > 0) { return l; } /* if (is_set(layers_state, l)) { return l; } */ } // the base layer is always active return 0; } // enable a layer void layer_enable(layer l) { if (l >= KB_LAYERS || l == 0) { return; } layers_active[l] += 1; set_layer(layers_state, l); if (l > layers_top) { layers_top = l; } } // disable a layer void layer_disable(layer l) { // base layer stays always on if (l >= KB_LAYERS || l == 0) { return; } if (layers_active[l] > 0) { layers_active[l] -= 1; } if (layers_active[l] == 0) { unset_layer(layers_state, l); } if (l == layers_top) { layers_top = highest_active_layer(); } // re-press affected keys for (u8 row=0; row