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