]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/cannonkeys/satisfaction75/satisfaction75.c
Refactoring wilba.tech PCBs, updating Rama Works U80-A (#6272)
[qmk_firmware.git] / keyboards / cannonkeys / satisfaction75 / satisfaction75.c
1 #include "satisfaction75.h"
2 #include "print.h"
3 #include "debug.h"
4
5 #include "ch.h"
6 #include "hal.h"
7
8 #ifdef QWIIC_MICRO_OLED_ENABLE
9 #include "micro_oled.h"
10 #include "qwiic.h"
11 #endif
12
13 #include "timer.h"
14
15 #include "raw_hid.h"
16 #include "dynamic_keymap.h"
17 #include "tmk_core/common/eeprom.h"
18
19 // HACK
20 #include "keyboards/wilba_tech/via_api.h" // Temporary hack
21 #include "keyboards/wilba_tech/via_keycodes.h" // Temporary hack
22
23
24 /* Artificial delay added to get media keys to work in the encoder*/
25 #define MEDIA_KEY_DELAY 10
26
27 uint16_t last_flush;
28
29 volatile uint8_t led_numlock = false;
30 volatile uint8_t led_capslock = false;
31 volatile uint8_t led_scrolllock = false;
32
33 uint8_t layer;
34
35 bool queue_for_send = false;
36 bool clock_set_mode = false;
37 uint8_t oled_mode = OLED_DEFAULT;
38 bool oled_sleeping = false;
39
40 uint8_t encoder_value = 32;
41 uint8_t encoder_mode = ENC_MODE_VOLUME;
42 uint8_t enabled_encoder_modes = 0x1F;
43
44 RTCDateTime last_timespec;
45 uint16_t last_minute = 0;
46
47 uint8_t time_config_idx = 0;
48 int8_t hour_config = 0;
49 int16_t minute_config = 0;
50 int8_t year_config = 0;
51 int8_t month_config = 0;
52 int8_t day_config = 0;
53 uint8_t previous_encoder_mode = 0;
54
55 backlight_config_t kb_backlight_config = {
56   .enable = true,
57   .breathing = true,
58   .level = BACKLIGHT_LEVELS
59 };
60
61 bool eeprom_is_valid(void)
62 {
63         return (eeprom_read_word(((void*)EEPROM_MAGIC_ADDR)) == EEPROM_MAGIC &&
64                         eeprom_read_byte(((void*)EEPROM_VERSION_ADDR)) == EEPROM_VERSION);
65 }
66
67 void eeprom_set_valid(bool valid)
68 {
69         eeprom_update_word(((void*)EEPROM_MAGIC_ADDR), valid ? EEPROM_MAGIC : 0xFFFF);
70         eeprom_update_byte(((void*)EEPROM_VERSION_ADDR), valid ? EEPROM_VERSION : 0xFF);
71 }
72
73 void eeprom_reset(void)
74 {
75         // Set the VIA specific EEPROM state as invalid.
76         eeprom_set_valid(false);
77         // Set the TMK/QMK EEPROM state as invalid.
78         eeconfig_disable();
79 }
80
81 #ifdef RAW_ENABLE
82
83 void raw_hid_receive( uint8_t *data, uint8_t length )
84 {
85         uint8_t *command_id = &(data[0]);
86         uint8_t *command_data = &(data[1]);
87         switch ( *command_id )
88         {
89                 case id_get_protocol_version:
90                 {
91                         command_data[0] = PROTOCOL_VERSION >> 8;
92                         command_data[1] = PROTOCOL_VERSION & 0xFF;
93                         break;
94                 }
95                 case id_get_keyboard_value:
96                 {
97       switch( command_data[0])
98       {
99         case id_uptime:
100         {
101           uint32_t value = timer_read32();
102           command_data[1] = (value >> 24 ) & 0xFF;
103           command_data[2] = (value >> 16 ) & 0xFF;
104           command_data[3] = (value >> 8 ) & 0xFF;
105           command_data[4] = value & 0xFF;
106           break;
107         }
108         case id_oled_default_mode:
109         {
110           uint8_t default_oled = eeprom_read_byte((uint8_t*)DYNAMIC_KEYMAP_DEFAULT_OLED);
111           command_data[1] = default_oled;
112           break;
113         }
114         case id_oled_mode:
115         {
116           command_data[1] = oled_mode;
117           break;
118
119         }
120         case id_encoder_modes:
121         {
122           command_data[1] = enabled_encoder_modes;
123           break;
124         }
125         case id_encoder_custom:
126         {
127           // uint8_t custom_encoder_idx = command_data[1];
128           // command_data[2] = 0x00;
129           // command_data[3] = 0x00;
130           // command_data[4] = 0x00;
131           // command_data[5] = 0x00;
132           // command_data[6] = 0x00;
133           // command_data[7] = 0x00;
134           break;
135         }
136         default:
137         {
138           *command_id = id_unhandled;
139           break;
140         }
141       }
142                         break;
143     }
144 #ifdef DYNAMIC_KEYMAP_ENABLE
145     case id_set_keyboard_value:
146     {
147       switch(command_data[0]){
148         case id_oled_default_mode:
149         {
150           eeprom_update_byte((uint8_t*)DYNAMIC_KEYMAP_DEFAULT_OLED, command_data[1]);
151           break;
152         }
153         case id_oled_mode:
154         {
155           oled_mode = command_data[1];
156           draw_ui();
157           break;
158         }
159         case id_encoder_modes:
160         {
161           enabled_encoder_modes = command_data[1];
162           eeprom_update_byte((uint8_t*)DYNAMIC_KEYMAP_ENABLED_ENCODER_MODES, enabled_encoder_modes);
163           break;
164         }
165         case id_encoder_custom:
166         {
167           // uint8_t custom_encoder_idx = command_data[1];
168           break;
169         }
170         default:
171         {
172           *command_id = id_unhandled;
173           break;
174         }
175       }
176       break;
177     }
178                 case id_dynamic_keymap_get_keycode:
179                 {
180                         uint16_t keycode = dynamic_keymap_get_keycode( command_data[0], command_data[1], command_data[2] );
181                         command_data[3] = keycode >> 8;
182                         command_data[4] = keycode & 0xFF;
183                         break;
184                 }
185                 case id_dynamic_keymap_set_keycode:
186                 {
187                         dynamic_keymap_set_keycode( command_data[0], command_data[1], command_data[2], ( command_data[3] << 8 ) | command_data[4] );
188                         break;
189                 }
190                 case id_dynamic_keymap_reset:
191                 {
192                         dynamic_keymap_reset();
193                         break;
194                 }
195                 case id_dynamic_keymap_macro_get_count:
196                 {
197                         command_data[0] = dynamic_keymap_macro_get_count();
198                         break;
199                 }
200                 case id_dynamic_keymap_macro_get_buffer_size:
201                 {
202                         uint16_t size = dynamic_keymap_macro_get_buffer_size();
203                         command_data[0] = size >> 8;
204                         command_data[1] = size & 0xFF;
205                         break;
206                 }
207                 case id_dynamic_keymap_macro_get_buffer:
208                 {
209                         uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
210                         uint16_t size = command_data[2]; // size <= 28
211                         dynamic_keymap_macro_get_buffer( offset, size, &command_data[3] );
212                         break;
213                 }
214                 case id_dynamic_keymap_macro_set_buffer:
215                 {
216                         uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
217                         uint16_t size = command_data[2]; // size <= 28
218                         dynamic_keymap_macro_set_buffer( offset, size, &command_data[3] );
219                         break;
220                 }
221                 case id_dynamic_keymap_macro_reset:
222                 {
223                         dynamic_keymap_macro_reset();
224                         break;
225                 }
226                 case id_dynamic_keymap_get_layer_count:
227                 {
228                         command_data[0] = dynamic_keymap_get_layer_count();
229                         break;
230                 }
231                 case id_dynamic_keymap_get_buffer:
232                 {
233                         uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
234                         uint16_t size = command_data[2]; // size <= 28
235                         dynamic_keymap_get_buffer( offset, size, &command_data[3] );
236                         break;
237                 }
238                 case id_dynamic_keymap_set_buffer:
239                 {
240                         uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
241                         uint16_t size = command_data[2]; // size <= 28
242                         dynamic_keymap_set_buffer( offset, size, &command_data[3] );
243                         break;
244                 }
245 #endif // DYNAMIC_KEYMAP_ENABLE
246                 case id_eeprom_reset:
247                 {
248                         eeprom_reset();
249                         break;
250                 }
251                 case id_bootloader_jump:
252                 {
253                         // Need to send data back before the jump
254                         // Informs host that the command is handled
255                         raw_hid_send( data, length );
256                         // Give host time to read it
257                         wait_ms(100);
258                         bootloader_jump();
259                         break;
260                 }
261                 default:
262                 {
263                         // Unhandled message.
264                         *command_id = id_unhandled;
265                         break;
266                 }
267         }
268
269         // Return same buffer with values changed
270         raw_hid_send( data, length );
271
272 }
273
274 #endif
275
276
277 void read_host_led_state(void) {
278   uint8_t leds = host_keyboard_leds();
279   if (leds & (1 << USB_LED_NUM_LOCK))    {
280     if (led_numlock == false){
281     led_numlock = true;}
282     } else {
283     if (led_numlock == true){
284     led_numlock = false;}
285     }
286   if (leds & (1 << USB_LED_CAPS_LOCK))   {
287     if (led_capslock == false){
288     led_capslock = true;}
289     } else {
290     if (led_capslock == true){
291     led_capslock = false;}
292     }
293   if (leds & (1 << USB_LED_SCROLL_LOCK)) {
294     if (led_scrolllock == false){
295     led_scrolllock = true;}
296     } else {
297     if (led_scrolllock == true){
298     led_scrolllock = false;}
299     }
300 }
301
302 uint32_t layer_state_set_kb(uint32_t state) {
303   state = layer_state_set_user(state);
304   layer = biton32(state);
305   queue_for_send = true;
306   return state;
307 }
308
309 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
310   queue_for_send = true;
311   switch (keycode) {
312     case OLED_TOGG:
313       if(!clock_set_mode){
314         if (record->event.pressed) {
315           oled_mode = (oled_mode + 1) % _NUM_OLED_MODES;
316           draw_ui();
317         }
318       }
319       return false;
320     case CLOCK_SET:
321       if (record->event.pressed) {
322         if(clock_set_mode){
323           pre_encoder_mode_change();
324           clock_set_mode = false;
325           encoder_mode = previous_encoder_mode;
326           post_encoder_mode_change();
327
328         }else{
329           previous_encoder_mode = encoder_mode;
330           pre_encoder_mode_change();
331           clock_set_mode = true;
332           encoder_mode = ENC_MODE_CLOCK_SET;
333           post_encoder_mode_change();
334         }
335       }
336       return false;
337     case ENC_PRESS:
338       if (record->event.pressed) {
339         uint16_t mapped_code = handle_encoder_press();
340         uint16_t held_keycode_timer = timer_read();
341         if(mapped_code != 0){
342           register_code(mapped_code);
343           while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
344           unregister_code(mapped_code);
345         }
346       } else {
347         // Do something else when release
348       }
349       return false;
350     default:
351       break;
352   }
353
354 #ifdef DYNAMIC_KEYMAP_ENABLE
355         // Handle macros
356         if (record->event.pressed) {
357                 if ( keycode >= MACRO00 && keycode <= MACRO15 )
358                 {
359                         uint8_t id = keycode - MACRO00;
360                         dynamic_keymap_macro_send(id);
361                         return false;
362                 }
363         }
364 #endif //DYNAMIC_KEYMAP_ENABLE
365
366   return process_record_user(keycode, record);
367 }
368
369
370 void encoder_update_kb(uint8_t index, bool clockwise) {
371   encoder_value = (encoder_value + (clockwise ? 1 : -1)) % 64;
372   queue_for_send = true;
373   if (index == 0) {
374     if (layer == 0){
375       uint16_t mapped_code = 0;
376       if (clockwise) {
377         mapped_code = handle_encoder_clockwise();
378       } else {
379         mapped_code = handle_encoder_ccw();
380       }
381       uint16_t held_keycode_timer = timer_read();
382       if(mapped_code != 0){
383         register_code(mapped_code);
384         while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
385         unregister_code(mapped_code);
386       }
387     } else {
388       if(clockwise){
389         change_encoder_mode(false);
390       } else {
391         change_encoder_mode(true);
392       }
393     }
394   }
395 }
396
397 void dynamic_keymap_custom_reset(void){
398   void *p = (void*)(DYNAMIC_KEYMAP_CUSTOM_BACKLIGHT);
399         void *end = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR);
400         while ( p != end ) {
401                 eeprom_update_byte(p, 0);
402                 ++p;
403         }
404   eeprom_update_byte((uint8_t*)DYNAMIC_KEYMAP_ENABLED_ENCODER_MODES, 0x1F);
405 }
406
407 void save_backlight_config_to_eeprom(){
408   eeprom_update_byte((uint8_t*)DYNAMIC_KEYMAP_CUSTOM_BACKLIGHT, kb_backlight_config.raw);
409 }
410
411 void load_custom_config(){
412   kb_backlight_config.raw = eeprom_read_byte((uint8_t*)DYNAMIC_KEYMAP_CUSTOM_BACKLIGHT);
413 #ifdef DYNAMIC_KEYMAP_ENABLE
414   oled_mode = eeprom_read_byte((uint8_t*)DYNAMIC_KEYMAP_DEFAULT_OLED);
415   enabled_encoder_modes = eeprom_read_byte((uint8_t*)DYNAMIC_KEYMAP_ENABLED_ENCODER_MODES);
416 #endif
417 }
418
419 void eeprom_init_kb(void)
420 {
421         // If the EEPROM has the magic, the data is good.
422         // OK to load from EEPROM.
423         if (eeprom_is_valid()) {
424                 load_custom_config();
425         } else  {
426                 // If the EEPROM has not been saved before, or is out of date,
427                 // save the default values to the EEPROM. Default values
428                 // come from construction of the zeal_backlight_config instance.
429                 //backlight_config_save();
430 #ifdef DYNAMIC_KEYMAP_ENABLE
431                 // This resets the keymaps in EEPROM to what is in flash.
432                 dynamic_keymap_reset();
433                 // This resets the macros in EEPROM to nothing.
434                 dynamic_keymap_macro_reset();
435     // Reset the custom stuff
436     dynamic_keymap_custom_reset();
437 #endif
438                 // Save the magic number last, in case saving was interrupted
439                 eeprom_set_valid(true);
440         }
441 }
442
443 void matrix_init_kb(void)
444 {
445         eeprom_init_kb();
446   rtcGetTime(&RTCD1, &last_timespec);
447   queue_for_send = true;
448   backlight_init_ports();
449         matrix_init_user();
450 }
451
452
453 void matrix_scan_kb(void) {
454   rtcGetTime(&RTCD1, &last_timespec);
455   uint16_t minutes_since_midnight = last_timespec.millisecond / 1000 / 60;
456
457   if (minutes_since_midnight != last_minute){
458     last_minute = minutes_since_midnight;
459     if(!oled_sleeping){
460       queue_for_send = true;
461     }
462   }
463 #ifdef QWIIC_MICRO_OLED_ENABLE
464   if (queue_for_send && oled_mode != OLED_OFF) {
465     oled_sleeping = false;
466     read_host_led_state();
467     draw_ui();
468     queue_for_send = false;
469   }
470   if (timer_elapsed(last_flush) > ScreenOffInterval && !oled_sleeping) {
471     send_command(DISPLAYOFF);      /* 0xAE */
472     oled_sleeping = true;
473   }
474 #endif
475 }
476