/* ---------------------------------------------------------------------------- * main() * ---------------------------------------------------------------------------- * Copyright (c) 2012 Ben Blazak * Released under The MIT License (MIT) (see "license.md") * Project located at * ------------------------------------------------------------------------- */ #include #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 // ---------------------------------------------------------------------------- // state of key presses 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]; // layer state static i8 layers_active[KB_LAYERS]; static layer layers_top; // sticky states 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; // key repeat config static const millis repeat_delay = 300; // ms before key repeat kicks in static const millis repeat_rate = 13; // send 1 / RATE key press // key repeat state static millis time_pressed[KB_ROWS][KB_COLUMNS]; static bool repeating[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= repeat_delay) { // start repeat repeating[row][col] = true; time_pressed[row][col] = t; /* debug_printf("start: %lu\n", diff); */ } else if (repeating[row][col] && diff >= repeat_rate) { // continue repeat time_pressed[row][col] = t; /* debug_printf("cont: %lu\n", diff); */ } } // ---------------------------------------------------------------------------- // init functions // ---------------------------------------------------------------------------- void init_hw() { kb_init(); usb_init(); while (!usb_configured()); } void init_sticky() { for (layer l=1; l < KB_LAYERS; l++) { layer_sticky[l] = false; } layer_sticky_on = false; mod_sticky = 0; layer_sticky_done = false; mod_sticky_done = false; } void init_layers() { for (layer l=0; l < KB_LAYERS; l++) { layers_active[l] = 0; } layers_active[0] = 1; layers_top = 0; for (u8 row=0; row 0; l--) { if (layers_active[l] > 0) { 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; 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 (l == layers_top) { layers_top = highest_active_layer(); } // re-press affected keys for (u8 row=0; row