aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio/audio_arm.c612
-rw-r--r--quantum/keymap_common.c2
-rw-r--r--quantum/keymap_extras/sendstring_german.h4
-rw-r--r--quantum/led_matrix.c391
-rw-r--r--quantum/led_matrix_drivers.c149
-rw-r--r--quantum/ledmatrix.h129
-rw-r--r--quantum/matrix.c2
-rw-r--r--quantum/process_keycode/process_clicky.c26
-rw-r--r--quantum/quantum.c69
-rw-r--r--quantum/quantum.h6
-rw-r--r--quantum/rgblight.c13
-rw-r--r--quantum/template/avr/config.h5
-rw-r--r--quantum/template/ps2avrgb/config.h5
13 files changed, 1079 insertions, 334 deletions
diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c
index 989f7a64b..f24ce4bd0 100644
--- a/quantum/audio/audio_arm.c
+++ b/quantum/audio/audio_arm.c
@@ -273,19 +273,24 @@ static const DACConversionGroup dacgrpcfg2 = {
273 .trigger = DAC_TRG(0) 273 .trigger = DAC_TRG(0)
274}; 274};
275 275
276void audio_init() 276void audio_init() {
277{ 277
278 278 if (audio_initialized) {
279 if (audio_initialized) 279 return;
280 return; 280 }
281 281
282 // Check EEPROM 282 // Check EEPROM
283 // if (!eeconfig_is_enabled()) 283 #if defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
284 // { 284 if (!eeconfig_is_enabled()) {
285 // eeconfig_init(); 285 eeconfig_init();
286 // } 286 }
287 // audio_config.raw = eeconfig_read_audio(); 287 audio_config.raw = eeconfig_read_audio();
288#else // ARM EEPROM
288 audio_config.enable = true; 289 audio_config.enable = true;
290 #ifdef AUDIO_CLICKY_ON
291 audio_config.clicky_enable = true;
292 #endif
293#endif // ARM EEPROM
289 294
290 /* 295 /*
291 * Starting DAC1 driver, setting up the output pin as analog as suggested 296 * Starting DAC1 driver, setting up the output pin as analog as suggested
@@ -308,16 +313,15 @@ void audio_init()
308 dacStartConversion(&DACD1, &dacgrpcfg1, (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); 313 dacStartConversion(&DACD1, &dacgrpcfg1, (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE);
309 dacStartConversion(&DACD2, &dacgrpcfg2, (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); 314 dacStartConversion(&DACD2, &dacgrpcfg2, (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE);
310 315
311 audio_initialized = true; 316 audio_initialized = true;
312 317
313 if (audio_config.enable) { 318 if (audio_config.enable) {
314 PLAY_SONG(startup_song); 319 PLAY_SONG(startup_song);
315 } 320 }
316 321
317} 322}
318 323
319void stop_all_notes() 324void stop_all_notes() {
320{
321 dprintf("audio stop all notes"); 325 dprintf("audio stop all notes");
322 326
323 if (!audio_initialized) { 327 if (!audio_initialized) {
@@ -342,347 +346,347 @@ void stop_all_notes()
342 } 346 }
343} 347}
344 348
345void stop_note(float freq) 349void stop_note(float freq) {
346{ 350 dprintf("audio stop note freq=%d", (int)freq);
347 dprintf("audio stop note freq=%d", (int)freq);
348 351
349 if (playing_note) { 352 if (playing_note) {
350 if (!audio_initialized) { 353 if (!audio_initialized) {
351 audio_init(); 354 audio_init();
352 } 355 }
353 for (int i = 7; i >= 0; i--) { 356 for (int i = 7; i >= 0; i--) {
354 if (frequencies[i] == freq) { 357 if (frequencies[i] == freq) {
355 frequencies[i] = 0; 358 frequencies[i] = 0;
356 volumes[i] = 0; 359 volumes[i] = 0;
357 for (int j = i; (j < 7); j++) { 360 for (int j = i; (j < 7); j++) {
358 frequencies[j] = frequencies[j+1]; 361 frequencies[j] = frequencies[j+1];
359 frequencies[j+1] = 0; 362 frequencies[j+1] = 0;
360 volumes[j] = volumes[j+1]; 363 volumes[j] = volumes[j+1];
361 volumes[j+1] = 0; 364 volumes[j+1] = 0;
362 }
363 break;
364 }
365 }
366 voices--;
367 if (voices < 0)
368 voices = 0;
369 if (voice_place >= voices) {
370 voice_place = 0;
371 }
372 if (voices == 0) {
373 STOP_CHANNEL_1();
374 STOP_CHANNEL_2();
375 gptStopTimer(&GPTD8);
376 frequency = 0;
377 frequency_alt = 0;
378 volume = 0;
379 playing_note = false;
380 } 365 }
366 break;
367 }
368 }
369 voices--;
370 if (voices < 0) {
371 voices = 0;
372 }
373 if (voice_place >= voices) {
374 voice_place = 0;
375 }
376 if (voices == 0) {
377 STOP_CHANNEL_1();
378 STOP_CHANNEL_2();
379 gptStopTimer(&GPTD8);
380 frequency = 0;
381 frequency_alt = 0;
382 volume = 0;
383 playing_note = false;
381 } 384 }
385 }
382} 386}
383 387
384#ifdef VIBRATO_ENABLE 388#ifdef VIBRATO_ENABLE
385 389
386float mod(float a, int b) 390float mod(float a, int b) {
387{ 391 float r = fmod(a, b);
388 float r = fmod(a, b); 392 return r < 0 ? r + b : r;
389 return r < 0 ? r + b : r;
390} 393}
391 394
392float vibrato(float average_freq) { 395float vibrato(float average_freq) {
393 #ifdef VIBRATO_STRENGTH_ENABLE 396 #ifdef VIBRATO_STRENGTH_ENABLE
394 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength); 397 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
395 #else 398 #else
396 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter]; 399 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
397 #endif 400 #endif
398 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH); 401 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
399 return vibrated_freq; 402 return vibrated_freq;
400} 403}
401 404
402#endif 405#endif
403 406
404static void gpt_cb8(GPTDriver *gptp) { 407static void gpt_cb8(GPTDriver *gptp) {
405 float freq; 408 float freq;
406 409
407 if (playing_note) { 410 if (playing_note) {
408 if (voices > 0) { 411 if (voices > 0) {
409 412
410 float freq_alt = 0; 413 float freq_alt = 0;
411 if (voices > 1) { 414 if (voices > 1) {
412 if (polyphony_rate == 0) { 415 if (polyphony_rate == 0) {
413 if (glissando) { 416 if (glissando) {
414 if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) { 417 if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
415 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2); 418 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
416 } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) { 419 } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
417 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2); 420 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
418 } else {
419 frequency_alt = frequencies[voices - 2];
420 }
421 } else {
422 frequency_alt = frequencies[voices - 2];
423 }
424
425 #ifdef VIBRATO_ENABLE
426 if (vibrato_strength > 0) {
427 freq_alt = vibrato(frequency_alt);
428 } else {
429 freq_alt = frequency_alt;
430 }
431 #else
432 freq_alt = frequency_alt;
433 #endif
434 }
435
436 if (envelope_index < 65535) {
437 envelope_index++;
438 }
439
440 freq_alt = voice_envelope(freq_alt);
441
442 if (freq_alt < 30.517578125) {
443 freq_alt = 30.52;
444 }
445
446 if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) {
447 UPDATE_CHANNEL_2_FREQ(freq_alt);
448 } else {
449 RESTART_CHANNEL_2();
450 }
451 //note_timbre;
452 }
453
454 if (polyphony_rate > 0) {
455 if (voices > 1) {
456 voice_place %= voices;
457 if (place++ > (frequencies[voice_place] / polyphony_rate)) {
458 voice_place = (voice_place + 1) % voices;
459 place = 0.0;
460 }
461 }
462
463 #ifdef VIBRATO_ENABLE
464 if (vibrato_strength > 0) {
465 freq = vibrato(frequencies[voice_place]);
466 } else {
467 freq = frequencies[voice_place];
468 }
469 #else
470 freq = frequencies[voice_place];
471 #endif
472 } else { 421 } else {
473 if (glissando) { 422 frequency_alt = frequencies[voices - 2];
474 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
475 frequency = frequency * pow(2, 440/frequency/12/2);
476 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
477 frequency = frequency * pow(2, -440/frequency/12/2);
478 } else {
479 frequency = frequencies[voices - 1];
480 }
481 } else {
482 frequency = frequencies[voices - 1];
483 }
484
485 #ifdef VIBRATO_ENABLE
486 if (vibrato_strength > 0) {
487 freq = vibrato(frequency);
488 } else {
489 freq = frequency;
490 }
491 #else
492 freq = frequency;
493 #endif
494 } 423 }
424 } else {
425 frequency_alt = frequencies[voices - 2];
426 }
495 427
496 if (envelope_index < 65535) { 428 #ifdef VIBRATO_ENABLE
497 envelope_index++; 429 if (vibrato_strength > 0) {
498 } 430 freq_alt = vibrato(frequency_alt);
499
500 freq = voice_envelope(freq);
501
502 if (freq < 30.517578125) {
503 freq = 30.52;
504 }
505
506
507 if (GET_CHANNEL_1_FREQ != (uint16_t)freq) {
508 UPDATE_CHANNEL_1_FREQ(freq);
509 } else { 431 } else {
510 RESTART_CHANNEL_1(); 432 freq_alt = frequency_alt;
511 } 433 }
512 //note_timbre; 434 #else
435 freq_alt = frequency_alt;
436 #endif
513 } 437 }
514 }
515 438
516 if (playing_notes) { 439 if (envelope_index < 65535) {
517 if (note_frequency > 0) { 440 envelope_index++;
518 #ifdef VIBRATO_ENABLE 441 }
519 if (vibrato_strength > 0) {
520 freq = vibrato(note_frequency);
521 } else {
522 freq = note_frequency;
523 }
524 #else
525 freq = note_frequency;
526 #endif
527
528 if (envelope_index < 65535) {
529 envelope_index++;
530 }
531 freq = voice_envelope(freq);
532 442
443 freq_alt = voice_envelope(freq_alt);
533 444
534 if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { 445 if (freq_alt < 30.517578125) {
535 UPDATE_CHANNEL_1_FREQ(freq); 446 freq_alt = 30.52;
536 UPDATE_CHANNEL_2_FREQ(freq); 447 }
537 } 448
538 //note_timbre; 449 if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) {
450 UPDATE_CHANNEL_2_FREQ(freq_alt);
539 } else { 451 } else {
540 // gptStopTimer(&GPTD6); 452 RESTART_CHANNEL_2();
541 // gptStopTimer(&GPTD7); 453 }
454 //note_timbre;
455 }
456
457 if (polyphony_rate > 0) {
458 if (voices > 1) {
459 voice_place %= voices;
460 if (place++ > (frequencies[voice_place] / polyphony_rate)) {
461 voice_place = (voice_place + 1) % voices;
462 place = 0.0;
463 }
542 } 464 }
543 465
544 note_position++; 466 #ifdef VIBRATO_ENABLE
545 bool end_of_note = false; 467 if (vibrato_strength > 0) {
546 if (GET_CHANNEL_1_FREQ > 0) { 468 freq = vibrato(frequencies[voice_place]);
547 if (!note_resting) 469 } else {
548 end_of_note = (note_position >= (note_length*8 - 1)); 470 freq = frequencies[voice_place];
549 else 471 }
550 end_of_note = (note_position >= (note_length*8)); 472 #else
473 freq = frequencies[voice_place];
474 #endif
475 } else {
476 if (glissando) {
477 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
478 frequency = frequency * pow(2, 440/frequency/12/2);
479 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
480 frequency = frequency * pow(2, -440/frequency/12/2);
481 } else {
482 frequency = frequencies[voices - 1];
483 }
551 } else { 484 } else {
552 end_of_note = (note_position >= (note_length*8)); 485 frequency = frequencies[voices - 1];
553 } 486 }
554 487
555 if (end_of_note) { 488 #ifdef VIBRATO_ENABLE
556 current_note++; 489 if (vibrato_strength > 0) {
557 if (current_note >= notes_count) { 490 freq = vibrato(frequency);
558 if (notes_repeat) { 491 } else {
559 current_note = 0; 492 freq = frequency;
560 } else { 493 }
561 STOP_CHANNEL_1(); 494 #else
562 STOP_CHANNEL_2(); 495 freq = frequency;
563 // gptStopTimer(&GPTD8); 496 #endif
564 playing_notes = false; 497 }
565 return;
566 }
567 }
568 if (!note_resting) {
569 note_resting = true;
570 current_note--;
571 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
572 note_frequency = 0;
573 note_length = 1;
574 } else {
575 note_frequency = (*notes_pointer)[current_note][0];
576 note_length = 1;
577 }
578 } else {
579 note_resting = false;
580 envelope_index = 0;
581 note_frequency = (*notes_pointer)[current_note][0];
582 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
583 }
584 498
585 note_position = 0; 499 if (envelope_index < 65535) {
586 } 500 envelope_index++;
587 } 501 }
588 502
589 if (!audio_config.enable) { 503 freq = voice_envelope(freq);
590 playing_notes = false;
591 playing_note = false;
592 }
593}
594 504
595void play_note(float freq, int vol) { 505 if (freq < 30.517578125) {
506 freq = 30.52;
507 }
596 508
597 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
598 509
599 if (!audio_initialized) { 510 if (GET_CHANNEL_1_FREQ != (uint16_t)freq) {
600 audio_init(); 511 UPDATE_CHANNEL_1_FREQ(freq);
512 } else {
513 RESTART_CHANNEL_1();
514 }
515 //note_timbre;
601 } 516 }
517 }
602 518
603 if (audio_config.enable && voices < 8) { 519 if (playing_notes) {
520 if (note_frequency > 0) {
521 #ifdef VIBRATO_ENABLE
522 if (vibrato_strength > 0) {
523 freq = vibrato(note_frequency);
524 } else {
525 freq = note_frequency;
526 }
527 #else
528 freq = note_frequency;
529 #endif
604 530
531 if (envelope_index < 65535) {
532 envelope_index++;
533 }
534 freq = voice_envelope(freq);
605 535
606 // Cancel notes if notes are playing
607 if (playing_notes)
608 stop_all_notes();
609 536
610 playing_note = true; 537 if (GET_CHANNEL_1_FREQ != (uint16_t)freq) {
538 UPDATE_CHANNEL_1_FREQ(freq);
539 UPDATE_CHANNEL_2_FREQ(freq);
540 }
541 //note_timbre;
542 } else {
543 // gptStopTimer(&GPTD6);
544 // gptStopTimer(&GPTD7);
545 }
611 546
612 envelope_index = 0; 547 note_position++;
548 bool end_of_note = false;
549 if (GET_CHANNEL_1_FREQ > 0) {
550 if (!note_resting)
551 end_of_note = (note_position >= (note_length*8 - 1));
552 else
553 end_of_note = (note_position >= (note_length*8));
554 } else {
555 end_of_note = (note_position >= (note_length*8));
556 }
613 557
614 if (freq > 0) { 558 if (end_of_note) {
615 frequencies[voices] = freq; 559 current_note++;
616 volumes[voices] = vol; 560 if (current_note >= notes_count) {
617 voices++; 561 if (notes_repeat) {
562 current_note = 0;
563 } else {
564 STOP_CHANNEL_1();
565 STOP_CHANNEL_2();
566 // gptStopTimer(&GPTD8);
567 playing_notes = false;
568 return;
569 }
570 }
571 if (!note_resting) {
572 note_resting = true;
573 current_note--;
574 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
575 note_frequency = 0;
576 note_length = 1;
577 } else {
578 note_frequency = (*notes_pointer)[current_note][0];
579 note_length = 1;
618 } 580 }
581 } else {
582 note_resting = false;
583 envelope_index = 0;
584 note_frequency = (*notes_pointer)[current_note][0];
585 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
586 }
619 587
620 gptStart(&GPTD8, &gpt8cfg1); 588 note_position = 0;
621 gptStartContinuous(&GPTD8, 2U);
622 RESTART_CHANNEL_1();
623 RESTART_CHANNEL_2();
624 } 589 }
590 }
625 591
592 if (!audio_config.enable) {
593 playing_notes = false;
594 playing_note = false;
595 }
626} 596}
627 597
628void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) 598void play_note(float freq, int vol) {
629{
630 599
631 if (!audio_initialized) { 600 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
632 audio_init(); 601
602 if (!audio_initialized) {
603 audio_init();
604 }
605
606 if (audio_config.enable && voices < 8) {
607
608 // Cancel notes if notes are playing
609 if (playing_notes) {
610 stop_all_notes();
633 } 611 }
634 612
635 if (audio_config.enable) { 613 playing_note = true;
636 614
637 // Cancel note if a note is playing 615 envelope_index = 0;
638 if (playing_note)
639 stop_all_notes();
640 616
641 playing_notes = true; 617 if (freq > 0) {
618 frequencies[voices] = freq;
619 volumes[voices] = vol;
620 voices++;
621 }
642 622
643 notes_pointer = np; 623 gptStart(&GPTD8, &gpt8cfg1);
644 notes_count = n_count; 624 gptStartContinuous(&GPTD8, 2U);
645 notes_repeat = n_repeat; 625 RESTART_CHANNEL_1();
626 RESTART_CHANNEL_2();
627 }
646 628
647 place = 0; 629}
648 current_note = 0;
649 630
650 note_frequency = (*notes_pointer)[current_note][0]; 631void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
651 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
652 note_position = 0;
653 632
654 gptStart(&GPTD8, &gpt8cfg1); 633 if (!audio_initialized) {
655 gptStartContinuous(&GPTD8, 2U); 634 audio_init();
656 RESTART_CHANNEL_1(); 635 }
657 RESTART_CHANNEL_2(); 636
637 if (audio_config.enable) {
638
639 // Cancel note if a note is playing
640 if (playing_note) {
641 stop_all_notes();
658 } 642 }
659 643
644 playing_notes = true;
645
646 notes_pointer = np;
647 notes_count = n_count;
648 notes_repeat = n_repeat;
649
650 place = 0;
651 current_note = 0;
652
653 note_frequency = (*notes_pointer)[current_note][0];
654 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
655 note_position = 0;
656
657 gptStart(&GPTD8, &gpt8cfg1);
658 gptStartContinuous(&GPTD8, 2U);
659 RESTART_CHANNEL_1();
660 RESTART_CHANNEL_2();
661 }
660} 662}
661 663
662bool is_playing_notes(void) { 664bool is_playing_notes(void) {
663 return playing_notes; 665 return playing_notes;
664} 666}
665 667
666bool is_audio_on(void) { 668bool is_audio_on(void) {
667 return (audio_config.enable != 0); 669 return (audio_config.enable != 0);
668} 670}
669 671
670void audio_toggle(void) { 672void audio_toggle(void) {
671 audio_config.enable ^= 1; 673 audio_config.enable ^= 1;
672 eeconfig_update_audio(audio_config.raw); 674 eeconfig_update_audio(audio_config.raw);
673 if (audio_config.enable) 675 if (audio_config.enable) {
674 audio_on_user(); 676 audio_on_user();
677 }
675} 678}
676 679
677void audio_on(void) { 680void audio_on(void) {
678 audio_config.enable = 1; 681 audio_config.enable = 1;
679 eeconfig_update_audio(audio_config.raw); 682 eeconfig_update_audio(audio_config.raw);
680 audio_on_user(); 683 audio_on_user();
681} 684}
682 685
683void audio_off(void) { 686void audio_off(void) {
684 audio_config.enable = 0; 687 stop_all_notes();
685 eeconfig_update_audio(audio_config.raw); 688 audio_config.enable = 0;
689 eeconfig_update_audio(audio_config.raw);
686} 690}
687 691
688#ifdef VIBRATO_ENABLE 692#ifdef VIBRATO_ENABLE
@@ -690,29 +694,29 @@ void audio_off(void) {
690// Vibrato rate functions 694// Vibrato rate functions
691 695
692void set_vibrato_rate(float rate) { 696void set_vibrato_rate(float rate) {
693 vibrato_rate = rate; 697 vibrato_rate = rate;
694} 698}
695 699
696void increase_vibrato_rate(float change) { 700void increase_vibrato_rate(float change) {
697 vibrato_rate *= change; 701 vibrato_rate *= change;
698} 702}
699 703
700void decrease_vibrato_rate(float change) { 704void decrease_vibrato_rate(float change) {
701 vibrato_rate /= change; 705 vibrato_rate /= change;
702} 706}
703 707
704#ifdef VIBRATO_STRENGTH_ENABLE 708#ifdef VIBRATO_STRENGTH_ENABLE
705 709
706void set_vibrato_strength(float strength) { 710void set_vibrato_strength(float strength) {
707 vibrato_strength = strength; 711 vibrato_strength = strength;
708} 712}
709 713
710void increase_vibrato_strength(float change) { 714void increase_vibrato_strength(float change) {
711 vibrato_strength *= change; 715 vibrato_strength *= change;
712} 716}
713 717
714void decrease_vibrato_strength(float change) { 718void decrease_vibrato_strength(float change) {
715 vibrato_strength /= change; 719 vibrato_strength /= change;
716} 720}
717 721
718#endif /* VIBRATO_STRENGTH_ENABLE */ 722#endif /* VIBRATO_STRENGTH_ENABLE */
@@ -722,45 +726,45 @@ void decrease_vibrato_strength(float change) {
722// Polyphony functions 726// Polyphony functions
723 727
724void set_polyphony_rate(float rate) { 728void set_polyphony_rate(float rate) {
725 polyphony_rate = rate; 729 polyphony_rate = rate;
726} 730}
727 731
728void enable_polyphony() { 732void enable_polyphony() {
729 polyphony_rate = 5; 733 polyphony_rate = 5;
730} 734}
731 735
732void disable_polyphony() { 736void disable_polyphony() {
733 polyphony_rate = 0; 737 polyphony_rate = 0;
734} 738}
735 739
736void increase_polyphony_rate(float change) { 740void increase_polyphony_rate(float change) {
737 polyphony_rate *= change; 741 polyphony_rate *= change;
738} 742}
739 743
740void decrease_polyphony_rate(float change) { 744void decrease_polyphony_rate(float change) {
741 polyphony_rate /= change; 745 polyphony_rate /= change;
742} 746}
743 747
744// Timbre function 748// Timbre function
745 749
746void set_timbre(float timbre) { 750void set_timbre(float timbre) {
747 note_timbre = timbre; 751 note_timbre = timbre;
748} 752}
749 753
750// Tempo functions 754// Tempo functions
751 755
752void set_tempo(uint8_t tempo) { 756void set_tempo(uint8_t tempo) {
753 note_tempo = tempo; 757 note_tempo = tempo;
754} 758}
755 759
756void decrease_tempo(uint8_t tempo_change) { 760void decrease_tempo(uint8_t tempo_change) {
757 note_tempo += tempo_change; 761 note_tempo += tempo_change;
758} 762}
759 763
760void increase_tempo(uint8_t tempo_change) { 764void increase_tempo(uint8_t tempo_change) {
761 if (note_tempo - tempo_change < 10) { 765 if (note_tempo - tempo_change < 10) {
762 note_tempo = 10; 766 note_tempo = 10;
763 } else { 767 } else {
764 note_tempo -= tempo_change; 768 note_tempo -= tempo_change;
765 } 769 }
766} 770}
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 1a6af9e08..9d2d331ce 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -127,7 +127,7 @@ action_t action_for_key(uint8_t layer, keypos_t key)
127 action.code = ACTION_LAYER_TAP_TOGGLE(keycode & 0xFF); 127 action.code = ACTION_LAYER_TAP_TOGGLE(keycode & 0xFF);
128 break; 128 break;
129 case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: 129 case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
130 mod = keycode & 0xF; 130 mod = mod_config(keycode & 0xF);
131 action_layer = (keycode >> 4) & 0xF; 131 action_layer = (keycode >> 4) & 0xF;
132 action.code = ACTION_LAYER_MODS(action_layer, mod); 132 action.code = ACTION_LAYER_MODS(action_layer, mod);
133 break; 133 break;
diff --git a/quantum/keymap_extras/sendstring_german.h b/quantum/keymap_extras/sendstring_german.h
index 1eaafee31..f20fab77d 100644
--- a/quantum/keymap_extras/sendstring_german.h
+++ b/quantum/keymap_extras/sendstring_german.h
@@ -67,7 +67,7 @@ const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = {
67 /* P Q R S T U V W */ 67 /* P Q R S T U V W */
68 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, 68 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
69 /* X Y Z [ \ ] ^ _ */ 69 /* X Y Z [ \ ] ^ _ */
70 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, DE_CIRC, DE_MINS, 70 KC_X, DE_Y, DE_Z, KC_LBRC, KC_BSLS, KC_RBRC, DE_CIRC, DE_MINS,
71 /* ` a b c d e f g */ 71 /* ` a b c d e f g */
72 DE_ACUT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, 72 DE_ACUT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
73 /* h i j k l m n o */ 73 /* h i j k l m n o */
@@ -75,7 +75,7 @@ const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = {
75 /* p q r s t u v w */ 75 /* p q r s t u v w */
76 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, 76 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
77 /* x y z { | } ~ DELETE */ 77 /* x y z { | } ~ DELETE */
78 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL 78 KC_X, DE_Y, DE_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
79}; 79};
80 80
81#endif 81#endif
diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c
new file mode 100644
index 000000000..8ef8abe71
--- /dev/null
+++ b/quantum/led_matrix.c
@@ -0,0 +1,391 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2017 Jack Humbert
3 * Copyright 2018 Yiancar
4 * Copyright 2019 Clueboard
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <stdint.h>
21#include <stdbool.h>
22#include "quantum.h"
23#include "ledmatrix.h"
24#include "progmem.h"
25#include "config.h"
26#include "eeprom.h"
27#include <string.h>
28#include <math.h>
29
30led_config_t led_matrix_config;
31
32#ifndef MAX
33 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
34#endif
35
36#ifndef MIN
37 #define MIN(a,b) ((a) < (b)? (a): (b))
38#endif
39
40#ifndef LED_DISABLE_AFTER_TIMEOUT
41 #define LED_DISABLE_AFTER_TIMEOUT 0
42#endif
43
44#ifndef LED_DISABLE_WHEN_USB_SUSPENDED
45 #define LED_DISABLE_WHEN_USB_SUSPENDED false
46#endif
47
48#ifndef EECONFIG_LED_MATRIX
49 #define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT
50#endif
51
52#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255
53 #define LED_MATRIX_MAXIMUM_BRIGHTNESS 255
54#endif
55
56bool g_suspend_state = false;
57
58// Global tick at 20 Hz
59uint32_t g_tick = 0;
60
61// Ticks since this key was last hit.
62uint8_t g_key_hit[LED_DRIVER_LED_COUNT];
63
64// Ticks since any key was last hit.
65uint32_t g_any_key_hit = 0;
66
67uint32_t eeconfig_read_led_matrix(void) {
68 return eeprom_read_dword(EECONFIG_LED_MATRIX);
69}
70
71void eeconfig_update_led_matrix(uint32_t config_value) {
72 eeprom_update_dword(EECONFIG_LED_MATRIX, config_value);
73}
74
75void eeconfig_update_led_matrix_default(void) {
76 dprintf("eeconfig_update_led_matrix_default\n");
77 led_matrix_config.enable = 1;
78 led_matrix_config.mode = LED_MATRIX_UNIFORM_BRIGHTNESS;
79 led_matrix_config.val = 128;
80 led_matrix_config.speed = 0;
81 eeconfig_update_led_matrix(led_matrix_config.raw);
82}
83
84void eeconfig_debug_led_matrix(void) {
85 dprintf("led_matrix_config eeprom\n");
86 dprintf("led_matrix_config.enable = %d\n", led_matrix_config.enable);
87 dprintf("led_matrix_config.mode = %d\n", led_matrix_config.mode);
88 dprintf("led_matrix_config.val = %d\n", led_matrix_config.val);
89 dprintf("led_matrix_config.speed = %d\n", led_matrix_config.speed);
90}
91
92// Last led hit
93#ifndef LED_HITS_TO_REMEMBER
94 #define LED_HITS_TO_REMEMBER 8
95#endif
96uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255};
97uint8_t g_last_led_count = 0;
98
99void map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i, uint8_t *led_count) {
100 led_matrix led;
101 *led_count = 0;
102
103 for (uint8_t i = 0; i < LED_DRIVER_LED_COUNT; i++) {
104 // map_index_to_led(i, &led);
105 led = g_leds[i];
106 if (row == led.matrix_co.row && column == led.matrix_co.col) {
107 led_i[*led_count] = i;
108 (*led_count)++;
109 }
110 }
111}
112
113void led_matrix_update_pwm_buffers(void) {
114 led_matrix_driver.flush();
115}
116
117void led_matrix_set_index_value(int index, uint8_t value) {
118 led_matrix_driver.set_value(index, value);
119}
120
121void led_matrix_set_index_value_all(uint8_t value) {
122 led_matrix_driver.set_value_all(value);
123}
124
125bool process_led_matrix(uint16_t keycode, keyrecord_t *record) {
126 if (record->event.pressed) {
127 uint8_t led[8], led_count;
128 map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
129 if (led_count > 0) {
130 for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) {
131 g_last_led_hit[i - 1] = g_last_led_hit[i - 2];
132 }
133 g_last_led_hit[0] = led[0];
134 g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1);
135 }
136 for(uint8_t i = 0; i < led_count; i++)
137 g_key_hit[led[i]] = 0;
138 g_any_key_hit = 0;
139 } else {
140 #ifdef LED_MATRIX_KEYRELEASES
141 uint8_t led[8], led_count;
142 map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
143 for(uint8_t i = 0; i < led_count; i++)
144 g_key_hit[led[i]] = 255;
145
146 g_any_key_hit = 255;
147 #endif
148 }
149 return true;
150}
151
152void led_matrix_set_suspend_state(bool state) {
153 g_suspend_state = state;
154}
155
156// All LEDs off
157void led_matrix_all_off(void) {
158 led_matrix_set_index_value_all(0);
159}
160
161// Uniform brightness
162void led_matrix_uniform_brightness(void) {
163 led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_config.val);
164}
165
166void led_matrix_custom(void) {}
167
168void led_matrix_task(void) {
169 if (!led_matrix_config.enable) {
170 led_matrix_all_off();
171 led_matrix_indicators();
172 return;
173 }
174
175 g_tick++;
176
177 if (g_any_key_hit < 0xFFFFFFFF) {
178 g_any_key_hit++;
179 }
180
181 for (int led = 0; led < LED_DRIVER_LED_COUNT; led++) {
182 if (g_key_hit[led] < 255) {
183 if (g_key_hit[led] == 254)
184 g_last_led_count = MAX(g_last_led_count - 1, 0);
185 g_key_hit[led]++;
186 }
187 }
188
189 // Ideally we would also stop sending zeros to the LED driver PWM buffers
190 // while suspended and just do a software shutdown. This is a cheap hack for now.
191 bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) ||
192 (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20));
193 uint8_t effect = suspend_backlight ? 0 : led_matrix_config.mode;
194
195 // this gets ticked at 20 Hz.
196 // each effect can opt to do calculations
197 // and/or request PWM buffer updates.
198 switch (effect) {
199 case LED_MATRIX_UNIFORM_BRIGHTNESS:
200 led_matrix_uniform_brightness();
201 break;
202 default:
203 led_matrix_custom();
204 break;
205 }
206
207 if (!suspend_backlight) {
208 led_matrix_indicators();
209 }
210
211 // Tell the LED driver to update its state
212 led_matrix_driver.flush();
213}
214
215void led_matrix_indicators(void) {
216 led_matrix_indicators_kb();
217 led_matrix_indicators_user();
218}
219
220__attribute__((weak))
221void led_matrix_indicators_kb(void) {}
222
223__attribute__((weak))
224void led_matrix_indicators_user(void) {}
225
226
227// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column)
228// {
229// if (row >= MATRIX_ROWS)
230// {
231// // Special value, 255=none, 254=all
232// *index = row;
233// }
234// else
235// {
236// // This needs updated to something like
237// // uint8_t led[8], led_count;
238// // map_row_column_to_led(row,column,led,&led_count);
239// // for(uint8_t i = 0; i < led_count; i++)
240// map_row_column_to_led(row, column, index);
241// }
242// }
243
244void led_matrix_init(void) {
245 led_matrix_driver.init();
246
247 // Wait half a second for the driver to finish initializing
248 wait_ms(500);
249
250 // clear the key hits
251 for (int led=0; led<LED_DRIVER_LED_COUNT; led++) {
252 g_key_hit[led] = 255;
253 }
254
255 if (!eeconfig_is_enabled()) {
256 dprintf("led_matrix_init_drivers eeconfig is not enabled.\n");
257 eeconfig_init();
258 eeconfig_update_led_matrix_default();
259 }
260
261 led_matrix_config.raw = eeconfig_read_led_matrix();
262
263 if (!led_matrix_config.mode) {
264 dprintf("led_matrix_init_drivers led_matrix_config.mode = 0. Write default values to EEPROM.\n");
265 eeconfig_update_led_matrix_default();
266 led_matrix_config.raw = eeconfig_read_led_matrix();
267 }
268
269 eeconfig_debug_led_matrix(); // display current eeprom values
270}
271
272// Deals with the messy details of incrementing an integer
273static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) {
274 int16_t new_value = value;
275 new_value += step;
276 return MIN(MAX(new_value, min), max);
277}
278
279static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) {
280 int16_t new_value = value;
281 new_value -= step;
282 return MIN(MAX(new_value, min), max);
283}
284
285// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) {
286// // 3 bytes per value
287// return EECONFIG_LED_MATRIX + (led * 3);
288// }
289
290// void backlight_get_key_value(uint8_t led, uint8_t *value) {
291// void *address = backlight_get_custom_key_value_eeprom_address(led);
292// value = eeprom_read_byte(address);
293// }
294
295// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) {
296// uint8_t led[8], led_count;
297// map_row_column_to_led(row,column,led,&led_count);
298// for(uint8_t i = 0; i < led_count; i++) {
299// if (led[i] < LED_DRIVER_LED_COUNT) {
300// void *address = backlight_get_custom_key_value_eeprom_address(led[i]);
301// eeprom_update_byte(address, value);
302// }
303// }
304// }
305
306uint32_t led_matrix_get_tick(void) {
307 return g_tick;
308}
309
310void led_matrix_toggle(void) {
311 led_matrix_config.enable ^= 1;
312 eeconfig_update_led_matrix(led_matrix_config.raw);
313}
314
315void led_matrix_enable(void) {
316 led_matrix_config.enable = 1;
317 eeconfig_update_led_matrix(led_matrix_config.raw);
318}
319
320void led_matrix_enable_noeeprom(void) {
321 led_matrix_config.enable = 1;
322}
323
324void led_matrix_disable(void) {
325 led_matrix_config.enable = 0;
326 eeconfig_update_led_matrix(led_matrix_config.raw);
327}
328
329void led_matrix_disable_noeeprom(void) {
330 led_matrix_config.enable = 0;
331}
332
333void led_matrix_step(void) {
334 led_matrix_config.mode++;
335 if (led_matrix_config.mode >= LED_MATRIX_EFFECT_MAX) {
336 led_matrix_config.mode = 1;
337 }
338 eeconfig_update_led_matrix(led_matrix_config.raw);
339}
340
341void led_matrix_step_reverse(void) {
342 led_matrix_config.mode--;
343 if (led_matrix_config.mode < 1) {
344 led_matrix_config.mode = LED_MATRIX_EFFECT_MAX - 1;
345 }
346 eeconfig_update_led_matrix(led_matrix_config.raw);
347}
348
349void led_matrix_increase_val(void) {
350 led_matrix_config.val = increment(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS);
351 eeconfig_update_led_matrix(led_matrix_config.raw);
352}
353
354void led_matrix_decrease_val(void) {
355 led_matrix_config.val = decrement(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS);
356 eeconfig_update_led_matrix(led_matrix_config.raw);
357}
358
359void led_matrix_increase_speed(void) {
360 led_matrix_config.speed = increment(led_matrix_config.speed, 1, 0, 3);
361 eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this
362}
363
364void led_matrix_decrease_speed(void) {
365 led_matrix_config.speed = decrement(led_matrix_config.speed, 1, 0, 3);
366 eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this
367}
368
369void led_matrix_mode(uint8_t mode, bool eeprom_write) {
370 led_matrix_config.mode = mode;
371 if (eeprom_write) {
372 eeconfig_update_led_matrix(led_matrix_config.raw);
373 }
374}
375
376uint8_t led_matrix_get_mode(void) {
377 return led_matrix_config.mode;
378}
379
380void led_matrix_set_value_noeeprom(uint8_t val) {
381 led_matrix_config.val = val;
382}
383
384void led_matrix_set_value(uint8_t val) {
385 led_matrix_set_value_noeeprom(val);
386 eeconfig_update_led_matrix(led_matrix_config.raw);
387}
388
389void backlight_set(uint8_t val) {
390 led_matrix_set_value(val);
391}
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c
new file mode 100644
index 000000000..4ee509ee5
--- /dev/null
+++ b/quantum/led_matrix_drivers.c
@@ -0,0 +1,149 @@
1/* Copyright 2018 James Laird-Wah
2 * Copyright 2019 Clueboard
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdint.h>
19#include <stdbool.h>
20#include "quantum.h"
21#include "ledmatrix.h"
22
23/* Each driver needs to define a struct:
24 *
25 * const led_matrix_driver_t led_matrix_driver;
26 *
27 * All members must be provided. Keyboard custom drivers must define this
28 * in their own files.
29 */
30
31#if defined(IS31FL3731) || defined(IS31FL3733)
32
33#if defined(IS31FL3731)
34 #include "is31fl3731-simple.h"
35#endif
36
37#include "i2c_master.h"
38
39static void init(void) {
40 i2c_init();
41 #ifdef IS31FL3731
42 #ifdef LED_DRIVER_ADDR_1
43 IS31FL3731_init(LED_DRIVER_ADDR_1);
44 #endif
45 #ifdef LED_DRIVER_ADDR_2
46 IS31FL3731_init(LED_DRIVER_ADDR_2);
47 #endif
48 #ifdef LED_DRIVER_ADDR_3
49 IS31FL3731_init(LED_DRIVER_ADDR_3);
50 #endif
51 #ifdef LED_DRIVER_ADDR_4
52 IS31FL3731_init(LED_DRIVER_ADDR_4);
53 #endif
54 #else
55 #ifdef LED_DRIVER_ADDR_1
56 IS31FL3733_init(LED_DRIVER_ADDR_1);
57 #endif
58 #ifdef LED_DRIVER_ADDR_2
59 IS31FL3733_init(LED_DRIVER_ADDR_2);
60 #endif
61 #ifdef LED_DRIVER_ADDR_3
62 IS31FL3733_init(LED_DRIVER_ADDR_3);
63 #endif
64 #ifdef LED_DRIVER_ADDR_4
65 IS31FL3733_init(LED_DRIVER_ADDR_4);
66 #endif
67 #endif
68
69 for (int index = 0; index < LED_DRIVER_LED_COUNT; index++) {
70 #ifdef IS31FL3731
71 IS31FL3731_set_led_control_register(index, true);
72 #else
73 IS31FL3733_set_led_control_register(index, true);
74 #endif
75 }
76 // This actually updates the LED drivers
77 #ifdef IS31FL3731
78 #ifdef LED_DRIVER_ADDR_1
79 IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
80 #endif
81 #ifdef LED_DRIVER_ADDR_2
82 IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
83 #endif
84 #ifdef LED_DRIVER_ADDR_3
85 IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
86 #endif
87 #ifdef LED_DRIVER_ADDR_4
88 IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
89 #endif
90 #else
91 #ifdef LED_DRIVER_ADDR_1
92 IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
93 #endif
94 #ifdef LED_DRIVER_ADDR_2
95 IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
96 #endif
97 #ifdef LED_DRIVER_ADDR_3
98 IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
99 #endif
100 #ifdef LED_DRIVER_ADDR_4
101 IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
102 #endif
103 #endif
104}
105
106static void flush(void) {
107 #ifdef IS31FL3731
108 #ifdef LED_DRIVER_ADDR_1
109 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
110 #endif
111 #ifdef LED_DRIVER_ADDR_2
112 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
113 #endif
114 #ifdef LED_DRIVER_ADDR_3
115 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
116 #endif
117 #ifdef LED_DRIVER_ADDR_4
118 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
119 #endif
120 #else
121 #ifdef LED_DRIVER_ADDR_1
122 IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
123 #endif
124 #ifdef LED_DRIVER_ADDR_2
125 IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
126 #endif
127 #ifdef LED_DRIVER_ADDR_3
128 IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
129 #endif
130 #ifdef LED_DRIVER_ADDR_4
131 IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
132 #endif
133 #endif
134}
135
136const led_matrix_driver_t led_matrix_driver = {
137 .init = init,
138 .flush = flush,
139#ifdef IS31FL3731
140 .set_value = IS31FL3731_set_value,
141 .set_value_all = IS31FL3731_set_value_all,
142#else
143 .set_value = IS31FL3733_set_value,
144 .set_value_all = IS31FL3733_set_value_all,
145#endif
146};
147
148
149#endif
diff --git a/quantum/ledmatrix.h b/quantum/ledmatrix.h
new file mode 100644
index 000000000..618c5d676
--- /dev/null
+++ b/quantum/ledmatrix.h
@@ -0,0 +1,129 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2017 Jack Humbert
3 * Copyright 2018 Yiancar
4 * Copyright 2019 Clueboard
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef LED_MATRIX_H
21#define LED_MATRIX_H
22
23
24#ifndef BACKLIGHT_ENABLE
25 #error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE
26#endif
27
28
29typedef struct Point {
30 uint8_t x;
31 uint8_t y;
32} __attribute__((packed)) Point;
33
34typedef struct led_matrix {
35 union {
36 uint8_t raw;
37 struct {
38 uint8_t row:4; // 16 max
39 uint8_t col:4; // 16 max
40 };
41 } matrix_co;
42 Point point;
43 uint8_t modifier:1;
44} __attribute__((packed)) led_matrix;
45
46extern const led_matrix g_leds[LED_DRIVER_LED_COUNT];
47
48typedef struct {
49 uint8_t index;
50 uint8_t value;
51} led_indicator;
52
53typedef union {
54 uint32_t raw;
55 struct {
56 bool enable :1;
57 uint8_t mode :6;
58 uint8_t hue :8; // Unused by led_matrix
59 uint8_t sat :8; // Unused by led_matrix
60 uint8_t val :8;
61 uint8_t speed :8;//EECONFIG needs to be increased to support this
62 };
63} led_config_t;
64
65enum led_matrix_effects {
66 LED_MATRIX_UNIFORM_BRIGHTNESS = 1,
67 // All new effects go above this line
68 LED_MATRIX_EFFECT_MAX
69};
70
71void led_matrix_set_index_value(int index, uint8_t value);
72void led_matrix_set_index_value_all(uint8_t value);
73
74// This runs after another backlight effect and replaces
75// colors already set
76void led_matrix_indicators(void);
77void led_matrix_indicators_kb(void);
78void led_matrix_indicators_user(void);
79
80void led_matrix_init(void);
81void led_matrix_setup_drivers(void);
82
83void led_matrix_set_suspend_state(bool state);
84void led_matrix_set_indicator_state(uint8_t state);
85
86void led_matrix_task(void);
87
88// This should not be called from an interrupt
89// (eg. from a timer interrupt).
90// Call this while idle (in between matrix scans).
91// If the buffer is dirty, it will update the driver with the buffer.
92void led_matrix_update_pwm_buffers(void);
93
94bool process_led_matrix(uint16_t keycode, keyrecord_t *record);
95
96uint32_t led_matrix_get_tick(void);
97
98void led_matrix_toggle(void);
99void led_matrix_enable(void);
100void led_matrix_enable_noeeprom(void);
101void led_matrix_disable(void);
102void led_matrix_disable_noeeprom(void);
103void led_matrix_step(void);
104void led_matrix_step_reverse(void);
105void led_matrix_increase_val(void);
106void led_matrix_decrease_val(void);
107void led_matrix_increase_speed(void);
108void led_matrix_decrease_speed(void);
109void led_matrix_mode(uint8_t mode, bool eeprom_write);
110void led_matrix_mode_noeeprom(uint8_t mode);
111uint8_t led_matrix_get_mode(void);
112void led_matrix_set_value(uint8_t mode);
113void led_matrix_set_value_noeeprom(uint8_t mode);
114
115typedef struct {
116 /* Perform any initialisation required for the other driver functions to work. */
117 void (*init)(void);
118
119 /* Set the brightness of a single LED in the buffer. */
120 void (*set_value)(int index, uint8_t value);
121 /* Set the brightness of all LEDS on the keyboard in the buffer. */
122 void (*set_value_all)(uint8_t value);
123 /* Flush any buffered changes to the hardware. */
124 void (*flush)(void);
125} led_matrix_driver_t;
126
127extern const led_matrix_driver_t led_matrix_driver;
128
129#endif
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 5b7a0e03b..f7cad1a0f 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -159,7 +159,7 @@ bool matrix_is_modified(void)
159inline 159inline
160bool matrix_is_on(uint8_t row, uint8_t col) 160bool matrix_is_on(uint8_t row, uint8_t col)
161{ 161{
162 return (matrix[row] & ((matrix_row_t)1<col)); 162 return (matrix[row] & ((matrix_row_t)1<<col));
163} 163}
164 164
165inline 165inline
diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c
index 8238c263f..34c3f620b 100644
--- a/quantum/process_keycode/process_clicky.c
+++ b/quantum/process_keycode/process_clicky.c
@@ -32,7 +32,7 @@ extern bool midi_activated;
32 32
33void clicky_play(void) { 33void clicky_play(void) {
34#ifndef NO_MUSIC_MODE 34#ifndef NO_MUSIC_MODE
35 if (music_activated || midi_activated) return; 35 if (music_activated || midi_activated || audio_config.enable) return;
36#endif // !NO_MUSIC_MODE 36#endif // !NO_MUSIC_MODE
37 clicky_song[0][0] = 2.0f * clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) ); 37 clicky_song[0][0] = 2.0f * clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
38 clicky_song[1][0] = clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) ); 38 clicky_song[1][0] = clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
@@ -73,27 +73,29 @@ void clicky_off(void) {
73} 73}
74 74
75bool is_clicky_on(void) { 75bool is_clicky_on(void) {
76 return (audio_config.clicky_enable != 0); 76 return (audio_config.clicky_enable != 0);
77} 77}
78 78
79bool process_clicky(uint16_t keycode, keyrecord_t *record) { 79bool process_clicky(uint16_t keycode, keyrecord_t *record) {
80 if (keycode == CLICKY_TOGGLE && record->event.pressed) { clicky_toggle(); } 80 if (keycode == CLICKY_TOGGLE && record->event.pressed) { clicky_toggle(); }
81 81
82 if (keycode == CLICKY_ENABLE && record->event.pressed) { clicky_on(); } 82 if (keycode == CLICKY_ENABLE && record->event.pressed) { clicky_on(); }
83 if (keycode == CLICKY_DISABLE && record->event.pressed) { clicky_off(); } 83 if (keycode == CLICKY_DISABLE && record->event.pressed) { clicky_off(); }
84 84
85 if (keycode == CLICKY_RESET && record->event.pressed) { clicky_freq_reset(); } 85 if (keycode == CLICKY_RESET && record->event.pressed) { clicky_freq_reset(); }
86 86
87 if (keycode == CLICKY_UP && record->event.pressed) { clicky_freq_up(); } 87 if (keycode == CLICKY_UP && record->event.pressed) { clicky_freq_up(); }
88 if (keycode == CLICKY_DOWN && record->event.pressed) { clicky_freq_down(); } 88 if (keycode == CLICKY_DOWN && record->event.pressed) { clicky_freq_down(); }
89 89
90 90
91 if ( audio_config.clicky_enable ) { 91 if (audio_config.enable && audio_config.clicky_enable) {
92 if (record->event.pressed) { 92 if (record->event.pressed) { // Leave this separate so it's easier to add upstroke sound
93 clicky_play();; 93 if (keycode != AU_OFF && keycode != AU_TOG) { // DO NOT PLAY if audio will be disabled, and causes issuse on ARM
94 clicky_play();
94 } 95 }
95 } 96 }
96 return true; 97 }
98 return true;
97} 99}
98 100
99#endif //AUDIO_CLICKY 101#endif //AUDIO_CLICKY
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 5d8ffe34e..376578ade 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -195,6 +195,13 @@ void reset_keyboard(void) {
195 #define RSPC_KEY KC_0 195 #define RSPC_KEY KC_0
196#endif 196#endif
197 197
198#ifndef LSPO_MOD
199 #define LSPO_MOD KC_LSFT
200#endif
201#ifndef RSPC_MOD
202 #define RSPC_MOD KC_RSFT
203#endif
204
198// Shift / Enter setup 205// Shift / Enter setup
199#ifndef SFTENT_KEY 206#ifndef SFTENT_KEY
200 #define SFTENT_KEY KC_ENT 207 #define SFTENT_KEY KC_ENT
@@ -674,14 +681,27 @@ bool process_record_quantum(keyrecord_t *record) {
674 } 681 }
675 else { 682 else {
676 #ifdef DISABLE_SPACE_CADET_ROLLOVER 683 #ifdef DISABLE_SPACE_CADET_ROLLOVER
677 if (get_mods() & MOD_BIT(KC_RSFT)) { 684 if (get_mods() & MOD_BIT(RSPC_MOD)) {
678 shift_interrupted[0] = true; 685 shift_interrupted[0] = true;
679 shift_interrupted[1] = true; 686 shift_interrupted[1] = true;
680 } 687 }
681 #endif 688 #endif
682 if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) { 689 if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) {
690 #ifdef DISABLE_SPACE_CADET_MODIFIER
691 unregister_mods(MOD_BIT(KC_LSFT));
692 #else
693 if( LSPO_MOD != KC_LSFT ){
694 unregister_mods(MOD_BIT(KC_LSFT));
695 register_mods(MOD_BIT(LSPO_MOD));
696 }
697 #endif
683 register_code(LSPO_KEY); 698 register_code(LSPO_KEY);
684 unregister_code(LSPO_KEY); 699 unregister_code(LSPO_KEY);
700 #ifndef DISABLE_SPACE_CADET_MODIFIER
701 if( LSPO_MOD != KC_LSFT ){
702 unregister_mods(MOD_BIT(LSPO_MOD));
703 }
704 #endif
685 } 705 }
686 unregister_mods(MOD_BIT(KC_LSFT)); 706 unregister_mods(MOD_BIT(KC_LSFT));
687 } 707 }
@@ -696,14 +716,27 @@ bool process_record_quantum(keyrecord_t *record) {
696 } 716 }
697 else { 717 else {
698 #ifdef DISABLE_SPACE_CADET_ROLLOVER 718 #ifdef DISABLE_SPACE_CADET_ROLLOVER
699 if (get_mods() & MOD_BIT(KC_LSFT)) { 719 if (get_mods() & MOD_BIT(LSPO_MOD)) {
700 shift_interrupted[0] = true; 720 shift_interrupted[0] = true;
701 shift_interrupted[1] = true; 721 shift_interrupted[1] = true;
702 } 722 }
703 #endif 723 #endif
704 if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) { 724 if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
725 #ifdef DISABLE_SPACE_CADET_MODIFIER
726 unregister_mods(MOD_BIT(KC_RSFT));
727 #else
728 if( RSPC_MOD != KC_RSFT ){
729 unregister_mods(MOD_BIT(KC_RSFT));
730 register_mods(MOD_BIT(RSPC_MOD));
731 }
732 #endif
705 register_code(RSPC_KEY); 733 register_code(RSPC_KEY);
706 unregister_code(RSPC_KEY); 734 unregister_code(RSPC_KEY);
735 #ifndef DISABLE_SPACE_CADET_MODIFIER
736 if ( RSPC_MOD != KC_RSFT ){
737 unregister_mods(MOD_BIT(RSPC_MOD));
738 }
739 #endif
707 } 740 }
708 unregister_mods(MOD_BIT(KC_RSFT)); 741 unregister_mods(MOD_BIT(KC_RSFT));
709 } 742 }
@@ -998,7 +1031,11 @@ void matrix_init_quantum() {
998 eeconfig_init(); 1031 eeconfig_init();
999 } 1032 }
1000 #ifdef BACKLIGHT_ENABLE 1033 #ifdef BACKLIGHT_ENABLE
1001 backlight_init_ports(); 1034 #ifdef LED_MATRIX_ENABLE
1035 led_matrix_init();
1036 #else
1037 backlight_init_ports();
1038 #endif
1002 #endif 1039 #endif
1003 #ifdef AUDIO_ENABLE 1040 #ifdef AUDIO_ENABLE
1004 audio_init(); 1041 audio_init();
@@ -1034,8 +1071,12 @@ void matrix_scan_quantum() {
1034 matrix_scan_combo(); 1071 matrix_scan_combo();
1035 #endif 1072 #endif
1036 1073
1037 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) 1074 #if defined(BACKLIGHT_ENABLE)
1038 backlight_task(); 1075 #if defined(LED_MATRIX_ENABLE)
1076 led_matrix_task();
1077 #elif defined(BACKLIGHT_PIN)
1078 backlight_task();
1079 #endif
1039 #endif 1080 #endif
1040 1081
1041 #ifdef RGB_MATRIX_ENABLE 1082 #ifdef RGB_MATRIX_ENABLE
@@ -1448,6 +1489,24 @@ void led_set(uint8_t usb_led)
1448 // PORTE &= ~(1<<6); 1489 // PORTE &= ~(1<<6);
1449 // } 1490 // }
1450 1491
1492#if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
1493 // Use backlight as Caps Lock indicator
1494 uint8_t bl_toggle_lvl = 0;
1495
1496 if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK) && !backlight_config.enable) {
1497 // Turning Caps Lock ON and backlight is disabled in config
1498 // Toggling backlight to the brightest level
1499 bl_toggle_lvl = BACKLIGHT_LEVELS;
1500 } else if (IS_LED_OFF(usb_led, USB_LED_CAPS_LOCK) && backlight_config.enable) {
1501 // Turning Caps Lock OFF and backlight is enabled in config
1502 // Toggling backlight and restoring config level
1503 bl_toggle_lvl = backlight_config.level;
1504 }
1505
1506 // Set level without modify backlight_config to keep ability to restore state
1507 backlight_set(bl_toggle_lvl);
1508#endif
1509
1451 led_set_kb(usb_led); 1510 led_set_kb(usb_led);
1452} 1511}
1453 1512
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 56a6a1a99..c6acf83e5 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -28,7 +28,11 @@
28#include "matrix.h" 28#include "matrix.h"
29#include "keymap.h" 29#include "keymap.h"
30#ifdef BACKLIGHT_ENABLE 30#ifdef BACKLIGHT_ENABLE
31 #include "backlight.h" 31 #ifdef LED_MATRIX_ENABLE
32 #include "ledmatrix.h"
33 #else
34 #include "backlight.h"
35 #endif
32#endif 36#endif
33#ifdef RGBLIGHT_ENABLE 37#ifdef RGBLIGHT_ENABLE
34 #include "rgblight.h" 38 #include "rgblight.h"
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 23420ddd8..22dce963c 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -19,6 +19,11 @@
19 #include <avr/eeprom.h> 19 #include <avr/eeprom.h>
20 #include <avr/interrupt.h> 20 #include <avr/interrupt.h>
21#endif 21#endif
22#ifdef STM32_EEPROM_ENABLE
23 #include "hal.h"
24 #include "eeprom.h"
25 #include "eeprom_stm32.h"
26#endif
22#include "wait.h" 27#include "wait.h"
23#include "progmem.h" 28#include "progmem.h"
24#include "timer.h" 29#include "timer.h"
@@ -120,15 +125,17 @@ void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
120 125
121 126
122uint32_t eeconfig_read_rgblight(void) { 127uint32_t eeconfig_read_rgblight(void) {
123 #ifdef __AVR__ 128 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
124 return eeprom_read_dword(EECONFIG_RGBLIGHT); 129 return eeprom_read_dword(EECONFIG_RGBLIGHT);
125 #else 130 #else
126 return 0; 131 return 0;
127 #endif 132 #endif
128} 133}
129void eeconfig_update_rgblight(uint32_t val) { 134void eeconfig_update_rgblight(uint32_t val) {
130 #ifdef __AVR__ 135 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
136 if (eeconfig_read_rgblight() != val) {
131 eeprom_update_dword(EECONFIG_RGBLIGHT, val); 137 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
138 }
132 #endif 139 #endif
133} 140}
134void eeconfig_update_rgblight_default(void) { 141void eeconfig_update_rgblight_default(void) {
@@ -331,7 +338,7 @@ void rgblight_disable_noeeprom(void) {
331#ifdef RGBLIGHT_USE_TIMER 338#ifdef RGBLIGHT_USE_TIMER
332 rgblight_timer_disable(); 339 rgblight_timer_disable();
333#endif 340#endif
334 _delay_ms(50); 341 wait_ms(50);
335 rgblight_set(); 342 rgblight_set();
336} 343}
337 344
diff --git a/quantum/template/avr/config.h b/quantum/template/avr/config.h
index d05b2cb98..a31fcf236 100644
--- a/quantum/template/avr/config.h
+++ b/quantum/template/avr/config.h
@@ -131,9 +131,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
131 */ 131 */
132 132
133/* key combination for magic key command */ 133/* key combination for magic key command */
134#define IS_COMMAND() ( \ 134/* defined by default; to change, uncomment and set to the combination you want */
135 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ 135// #define IS_COMMAND() (get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
136)
137 136
138/* control how magic key switches layers */ 137/* control how magic key switches layers */
139//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true 138//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
diff --git a/quantum/template/ps2avrgb/config.h b/quantum/template/ps2avrgb/config.h
index 4ff3513bc..01cdf932e 100644
--- a/quantum/template/ps2avrgb/config.h
+++ b/quantum/template/ps2avrgb/config.h
@@ -42,8 +42,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
42 42
43#define NO_UART 1 43#define NO_UART 1
44 44
45/* key combination for command */ 45/* key combination for magic key command */
46#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) 46/* defined by default; to change, uncomment and set to the combination you want */
47// #define IS_COMMAND() (get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
47 48
48/* Bootmagic Lite key configuration */ 49/* Bootmagic Lite key configuration */
49// #define BOOTMAGIC_LITE_ROW 0 50// #define BOOTMAGIC_LITE_ROW 0