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