]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/lfkeyboards/lfk87/lfk87.c
Fix the LFKeyboards so they work with the QMK Configurator (#4591)
[qmk_firmware.git] / keyboards / lfkeyboards / lfk87 / lfk87.c
1
2 #include <avr/sfr_defs.h>
3 #include <avr/timer_avr.h>
4 #include <avr/wdt.h>
5 #include "lfk87.h"
6 #include "keymap.h"
7 #include "issi.h"
8 #include "TWIlib.h"
9 #include "lighting.h"
10 #include "debug.h"
11 #include "quantum.h"
12
13 uint16_t click_hz = CLICK_HZ;
14 uint16_t click_time = CLICK_MS;
15 uint8_t click_toggle = CLICK_ENABLED;
16
17 __attribute__((weak))
18 const Layer_Info layer_info[] = {
19     // Layer     Mask           Red     Green   Blue
20     {0x00000000, 0xFFFFFFFF, {0x00, 0xFF, 0x00}}, // base layers - green
21     {0x00000002, 0xFFFFFFFE, {0x00, 0x00, 0xFF}}, // function layer - blue
22     {0x00000004, 0xFFFFFFFC, {0xFF, 0x00, 0xFF}}, // settings layer - magenta
23     {0xFFFFFFFF, 0xFFFFFFFF, {0xFF, 0xFF, 0xFF}}, // unknown layer - REQUIRED - white
24 };
25
26 void matrix_init_kb(void)
27 {
28     // put your keyboard start-up code here
29     // runs once when the firmware starts up
30     matrix_init_user();
31     set_rgb(31, 0x00, 0x00, 0x00);  // Caps lock
32     set_rgb(32, 0xFF, 0x00, 0x00);  // Layer indicator, start red
33 #ifndef AUDIO_ENABLE
34     // If we're not using the audio pin, drive it low
35     sbi(DDRC, 6);
36     cbi(PORTC, 6);
37 #endif
38 #ifdef ISSI_ENABLE
39     issi_init();
40 #endif
41 #ifdef WATCHDOG_ENABLE
42     // This is done after turning the layer LED red, if we're caught in a loop
43     // we should get a flashing red light
44     wdt_enable(WDTO_500MS);
45 #endif
46 }
47
48 void matrix_scan_kb(void)
49 {
50 #ifdef WATCHDOG_ENABLE
51     wdt_reset();
52 #endif
53 #ifdef ISSI_ENABLE
54     // switch/underglow lighting update
55     static uint32_t issi_device = 0;
56     static uint32_t twi_last_ready = 0;
57     if(twi_last_ready > 1000){
58         // Its been way too long since the last ISSI update, reset the I2C bus and start again
59         twi_last_ready = 0;
60         TWIInit();
61         force_issi_refresh();
62     }
63     if(isTWIReady()){
64         twi_last_ready = 0;
65         // If the i2c bus is available, kick off the issi update, alternate between devices
66         update_issi(issi_device, issi_device);
67         if(issi_device){
68             issi_device = 0;
69         }else{
70             issi_device = 3;
71         }
72     }else{
73         twi_last_ready++;
74     }
75 #endif
76     // Update layer indicator LED
77     //
78     // Not sure how else to reliably do this... TMK has the 'hook_layer_change'
79     // but can't find QMK equiv
80     static uint32_t layer_indicator = -1;
81     if(layer_indicator != layer_state){
82         for(uint32_t i=0;; i++){
83             // the layer_info list should end with layer 0xFFFF
84             // it will break this out of the loop and define the unknown layer color
85             if((layer_info[i].layer == (layer_state & layer_info[i].mask)) || (layer_info[i].layer == 0xFFFFFFFF)){
86                 set_rgb(32, layer_info[i].color.red, layer_info[i].color.green, layer_info[i].color.blue);
87                 layer_indicator = layer_state;
88                 break;
89             }
90         }
91     }
92     matrix_scan_user();
93 }
94
95 void click(uint16_t freq, uint16_t duration){
96 #ifdef AUDIO_ENABLE
97     if(freq >= 100 && freq <= 20000 && duration < 100){
98         play_note(freq, 10);
99         for (uint16_t i = 0; i < duration; i++){
100             _delay_ms(1);
101         }
102         stop_all_notes();
103     }
104 #endif
105 }
106
107 bool process_record_kb(uint16_t keycode, keyrecord_t* record)
108 {
109     if (click_toggle && record->event.pressed){
110         click(click_hz, click_time);
111     }
112     if (keycode == RESET) {
113         reset_keyboard_kb();
114     } else {
115     }
116     return process_record_user(keycode, record);
117 }
118
119 void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
120 {
121 #ifdef AUDIO_ENABLE
122     int8_t sign = 1;
123 #endif
124     if(id == LFK_ESC_TILDE){
125         // Send ~ on shift-esc
126         void (*method)(uint8_t) = (event->event.pressed) ? &add_key : &del_key;
127         uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
128         method(shifted ? KC_GRAVE : KC_ESCAPE);
129         send_keyboard_report();
130     }else if(event->event.pressed){
131         switch(id){
132             case LFK_SET_DEFAULT_LAYER:
133                 // set/save the current base layer to eeprom, falls through to LFK_CLEAR
134                 eeconfig_update_default_layer(1UL << opt);
135                 default_layer_set(1UL << opt);
136             case LFK_CLEAR:
137                 // Go back to default layer
138                 layer_clear();
139                 break;
140 #ifdef ISSI_ENABLE
141             case LFK_LED_TEST:
142                 led_test();
143                 break;
144 #endif
145 #ifdef AUDIO_ENABLE
146             case LFK_CLICK_FREQ_LOWER:
147                 sign = -1;  // continue to next statement
148             case LFK_CLICK_FREQ_HIGHER:
149                 click_hz += sign * 100;
150                 click(click_hz, click_time);
151                 break;
152             case LFK_CLICK_TOGGLE:
153                 if(click_toggle){
154                     click_toggle = 0;
155                     click(4000, 100);
156                     click(1000, 100);
157                 }else{
158                     click_toggle = 1;
159                     click(1000, 100);
160                     click(4000, 100);
161                 }
162                 break;
163             case LFK_CLICK_TIME_SHORTER:
164                 sign = -1;  // continue to next statement
165             case LFK_CLICK_TIME_LONGER:
166                 click_time += sign;
167                 click(click_hz, click_time);
168                 break;
169 #endif
170         }
171     }
172 }
173
174 void reset_keyboard_kb(){
175 #ifdef WATCHDOG_ENABLE
176     MCUSR = 0;
177     wdt_disable();
178     wdt_reset();
179 #endif
180     set_rgb(31, 0x00, 0xFF, 0xFF);
181     set_rgb(32, 0x00, 0xFF, 0xFF);
182     force_issi_refresh();
183     reset_keyboard();
184 }
185
186 void led_set_kb(uint8_t usb_led)
187 {
188     // Set capslock LED to Blue
189     if (usb_led & (1 << USB_LED_CAPS_LOCK)) {
190         set_rgb(31, 0x00, 0x00, 0x7F);
191     }else{
192         set_rgb(31, 0x00, 0x00, 0x00);
193     }
194     led_set_user(usb_led);
195 }
196
197 // Lighting info, see lighting.h for details
198 const uint8_t switch_matrices[] = {0, 1};
199 const uint8_t rgb_matrices[] = {6, 7};
200
201 // RGB Map:
202 //   27  29  10   9   8   7   6
203 // 26                                   5
204 // 25                                   4
205 // 24                                   3
206 //   23  22  21  20  14  15  11   1   2
207 const uint8_t rgb_sequence[] = {
208     27, 29, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 11, 15, 14, 20, 21, 22, 23, 24, 25, 26
209 };
210
211 // Maps switch LEDs from Row/Col to ISSI matrix.
212 // Value breakdown:
213 //     Bit     | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
214 //             |   | ISSI Col  |    ISSI Row   |
215 //             /   |
216 //             Device
217 const uint8_t switch_leds[MATRIX_ROWS][MATRIX_COLS] =
218 LAYOUT_tkl_ansi(
219   0x19, 0x18,   0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94,   0x93,   0x92, 0x91,
220   0x29, 0x28,    0x27,  0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3,   0xA2, 0xA1,
221   0x39, 0x38,      0x37,  0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5,     0xB3,
222   0x49, 0x48,    0x47,     0x45, 0x44, 0x43, 0x42, 0x41, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5,          0xC4,   0xC2,
223   0x59, 0x58,   0x57,  0x56,  0x55,             0x51,                   0xD6, 0xE5, 0xE4,         0xE3, 0xE2, 0xE1,
224   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);