diff options
Diffstat (limited to 'quantum/quantum.c')
-rw-r--r-- | quantum/quantum.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/quantum/quantum.c b/quantum/quantum.c index 006464e5a..3f2edfc92 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c | |||
@@ -655,6 +655,9 @@ void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { | |||
655 | } | 655 | } |
656 | 656 | ||
657 | void matrix_init_quantum() { | 657 | void matrix_init_quantum() { |
658 | #ifdef BACKLIGHT_ENABLE | ||
659 | backlight_init_ports(); | ||
660 | #endif | ||
658 | matrix_init_kb(); | 661 | matrix_init_kb(); |
659 | } | 662 | } |
660 | 663 | ||
@@ -673,6 +676,7 @@ void matrix_scan_quantum() { | |||
673 | 676 | ||
674 | matrix_scan_kb(); | 677 | matrix_scan_kb(); |
675 | } | 678 | } |
679 | |||
676 | #ifdef AUDIO_ENABLE | 680 | #ifdef AUDIO_ENABLE |
677 | bool is_music_on(void) { | 681 | bool is_music_on(void) { |
678 | return (music_activated != 0); | 682 | return (music_activated != 0); |
@@ -698,6 +702,348 @@ void matrix_scan_quantum() { | |||
698 | 702 | ||
699 | #endif | 703 | #endif |
700 | 704 | ||
705 | |||
706 | #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) | ||
707 | |||
708 | static const uint8_t backlight_pin = BACKLIGHT_PIN; | ||
709 | |||
710 | #if BACKLIGHT_PIN == B7 | ||
711 | # define COM1x1 COM1C1 | ||
712 | # define OCR1x OCR1C | ||
713 | #elif BACKLIGHT_PIN == B6 | ||
714 | # define COM1x1 COM1B1 | ||
715 | # define OCR1x OCR1B | ||
716 | #elif BACKLIGHT_PIN == B5 | ||
717 | # define COM1x1 COM1A1 | ||
718 | # define OCR1x OCR1A | ||
719 | #else | ||
720 | # error "Backlight pin not supported - use B5, B6, or B7" | ||
721 | #endif | ||
722 | |||
723 | __attribute__ ((weak)) | ||
724 | void backlight_init_ports(void) | ||
725 | { | ||
726 | |||
727 | // Setup backlight pin as output and output low. | ||
728 | // DDRx |= n | ||
729 | _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); | ||
730 | // PORTx &= ~n | ||
731 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||
732 | |||
733 | // Use full 16-bit resolution. | ||
734 | ICR1 = 0xFFFF; | ||
735 | |||
736 | // I could write a wall of text here to explain... but TL;DW | ||
737 | // Go read the ATmega32u4 datasheet. | ||
738 | // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on | ||
739 | |||
740 | // Pin PB7 = OCR1C (Timer 1, Channel C) | ||
741 | // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 | ||
742 | // (i.e. start high, go low when counter matches.) | ||
743 | // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0 | ||
744 | // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1 | ||
745 | |||
746 | TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010; | ||
747 | TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; | ||
748 | |||
749 | backlight_init(); | ||
750 | #ifdef BACKLIGHT_BREATHING | ||
751 | breathing_defaults(); | ||
752 | #endif | ||
753 | } | ||
754 | |||
755 | __attribute__ ((weak)) | ||
756 | void backlight_set(uint8_t level) | ||
757 | { | ||
758 | // Prevent backlight blink on lowest level | ||
759 | // PORTx &= ~n | ||
760 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||
761 | |||
762 | if ( level == 0 ) { | ||
763 | // Turn off PWM control on backlight pin, revert to output low. | ||
764 | TCCR1A &= ~(_BV(COM1x1)); | ||
765 | OCR1x = 0x0; | ||
766 | } else if ( level == BACKLIGHT_LEVELS ) { | ||
767 | // Turn on PWM control of backlight pin | ||
768 | TCCR1A |= _BV(COM1x1); | ||
769 | // Set the brightness | ||
770 | OCR1x = 0xFFFF; | ||
771 | } else { | ||
772 | // Turn on PWM control of backlight pin | ||
773 | TCCR1A |= _BV(COM1x1); | ||
774 | // Set the brightness | ||
775 | OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2)); | ||
776 | } | ||
777 | |||
778 | #ifdef BACKLIGHT_BREATHING | ||
779 | breathing_intensity_default(); | ||
780 | #endif | ||
781 | } | ||
782 | |||
783 | |||
784 | #ifdef BACKLIGHT_BREATHING | ||
785 | |||
786 | #define BREATHING_NO_HALT 0 | ||
787 | #define BREATHING_HALT_OFF 1 | ||
788 | #define BREATHING_HALT_ON 2 | ||
789 | |||
790 | static uint8_t breath_intensity; | ||
791 | static uint8_t breath_speed; | ||
792 | static uint16_t breathing_index; | ||
793 | static uint8_t breathing_halt; | ||
794 | |||
795 | void breathing_enable(void) | ||
796 | { | ||
797 | if (get_backlight_level() == 0) | ||
798 | { | ||
799 | breathing_index = 0; | ||
800 | } | ||
801 | else | ||
802 | { | ||
803 | // Set breathing_index to be at the midpoint (brightest point) | ||
804 | breathing_index = 0x20 << breath_speed; | ||
805 | } | ||
806 | |||
807 | breathing_halt = BREATHING_NO_HALT; | ||
808 | |||
809 | // Enable breathing interrupt | ||
810 | TIMSK1 |= _BV(OCIE1A); | ||
811 | } | ||
812 | |||
813 | void breathing_pulse(void) | ||
814 | { | ||
815 | if (get_backlight_level() == 0) | ||
816 | { | ||
817 | breathing_index = 0; | ||
818 | } | ||
819 | else | ||
820 | { | ||
821 | // Set breathing_index to be at the midpoint + 1 (brightest point) | ||
822 | breathing_index = 0x21 << breath_speed; | ||
823 | } | ||
824 | |||
825 | breathing_halt = BREATHING_HALT_ON; | ||
826 | |||
827 | // Enable breathing interrupt | ||
828 | TIMSK1 |= _BV(OCIE1A); | ||
829 | } | ||
830 | |||
831 | void breathing_disable(void) | ||
832 | { | ||
833 | // Disable breathing interrupt | ||
834 | TIMSK1 &= ~_BV(OCIE1A); | ||
835 | backlight_set(get_backlight_level()); | ||
836 | } | ||
837 | |||
838 | void breathing_self_disable(void) | ||
839 | { | ||
840 | if (get_backlight_level() == 0) | ||
841 | { | ||
842 | breathing_halt = BREATHING_HALT_OFF; | ||
843 | } | ||
844 | else | ||
845 | { | ||
846 | breathing_halt = BREATHING_HALT_ON; | ||
847 | } | ||
848 | |||
849 | //backlight_set(get_backlight_level()); | ||
850 | } | ||
851 | |||
852 | void breathing_toggle(void) | ||
853 | { | ||
854 | if (!is_breathing()) | ||
855 | { | ||
856 | if (get_backlight_level() == 0) | ||
857 | { | ||
858 | breathing_index = 0; | ||
859 | } | ||
860 | else | ||
861 | { | ||
862 | // Set breathing_index to be at the midpoint + 1 (brightest point) | ||
863 | breathing_index = 0x21 << breath_speed; | ||
864 | } | ||
865 | |||
866 | breathing_halt = BREATHING_NO_HALT; | ||
867 | } | ||
868 | |||
869 | // Toggle breathing interrupt | ||
870 | TIMSK1 ^= _BV(OCIE1A); | ||
871 | |||
872 | // Restore backlight level | ||
873 | if (!is_breathing()) | ||
874 | { | ||
875 | backlight_set(get_backlight_level()); | ||
876 | } | ||
877 | } | ||
878 | |||
879 | bool is_breathing(void) | ||
880 | { | ||
881 | return (TIMSK1 && _BV(OCIE1A)); | ||
882 | } | ||
883 | |||
884 | void breathing_intensity_default(void) | ||
885 | { | ||
886 | //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS); | ||
887 | breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2)); | ||
888 | } | ||
889 | |||
890 | void breathing_intensity_set(uint8_t value) | ||
891 | { | ||
892 | breath_intensity = value; | ||
893 | } | ||
894 | |||
895 | void breathing_speed_default(void) | ||
896 | { | ||
897 | breath_speed = 4; | ||
898 | } | ||
899 | |||
900 | void breathing_speed_set(uint8_t value) | ||
901 | { | ||
902 | bool is_breathing_now = is_breathing(); | ||
903 | uint8_t old_breath_speed = breath_speed; | ||
904 | |||
905 | if (is_breathing_now) | ||
906 | { | ||
907 | // Disable breathing interrupt | ||
908 | TIMSK1 &= ~_BV(OCIE1A); | ||
909 | } | ||
910 | |||
911 | breath_speed = value; | ||
912 | |||
913 | if (is_breathing_now) | ||
914 | { | ||
915 | // Adjust index to account for new speed | ||
916 | breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed; | ||
917 | |||
918 | // Enable breathing interrupt | ||
919 | TIMSK1 |= _BV(OCIE1A); | ||
920 | } | ||
921 | |||
922 | } | ||
923 | |||
924 | void breathing_speed_inc(uint8_t value) | ||
925 | { | ||
926 | if ((uint16_t)(breath_speed - value) > 10 ) | ||
927 | { | ||
928 | breathing_speed_set(0); | ||
929 | } | ||
930 | else | ||
931 | { | ||
932 | breathing_speed_set(breath_speed - value); | ||
933 | } | ||
934 | } | ||
935 | |||
936 | void breathing_speed_dec(uint8_t value) | ||
937 | { | ||
938 | if ((uint16_t)(breath_speed + value) > 10 ) | ||
939 | { | ||
940 | breathing_speed_set(10); | ||
941 | } | ||
942 | else | ||
943 | { | ||
944 | breathing_speed_set(breath_speed + value); | ||
945 | } | ||
946 | } | ||
947 | |||
948 | void breathing_defaults(void) | ||
949 | { | ||
950 | breathing_intensity_default(); | ||
951 | breathing_speed_default(); | ||
952 | breathing_halt = BREATHING_NO_HALT; | ||
953 | } | ||
954 | |||
955 | /* Breathing Sleep LED brighness(PWM On period) table | ||
956 | * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle | ||
957 | * | ||
958 | * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 | ||
959 | * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } | ||
960 | */ | ||
961 | static const uint8_t breathing_table[64] PROGMEM = { | ||
962 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, | ||
963 | 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, | ||
964 | 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, | ||
965 | 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
966 | }; | ||
967 | |||
968 | ISR(TIMER1_COMPA_vect) | ||
969 | { | ||
970 | // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity; | ||
971 | |||
972 | |||
973 | uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F; | ||
974 | |||
975 | if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F))) | ||
976 | { | ||
977 | // Disable breathing interrupt | ||
978 | TIMSK1 &= ~_BV(OCIE1A); | ||
979 | } | ||
980 | |||
981 | OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity; | ||
982 | |||
983 | } | ||
984 | |||
985 | |||
986 | |||
987 | #endif // breathing | ||
988 | |||
989 | #else // backlight | ||
990 | |||
991 | __attribute__ ((weak)) | ||
992 | void backlight_init_ports(void) | ||
993 | { | ||
994 | |||
995 | } | ||
996 | |||
997 | __attribute__ ((weak)) | ||
998 | void backlight_set(uint8_t level) | ||
999 | { | ||
1000 | |||
1001 | } | ||
1002 | |||
1003 | #endif // backlight | ||
1004 | |||
1005 | |||
1006 | |||
1007 | __attribute__ ((weak)) | ||
1008 | void led_set_user(uint8_t usb_led) { | ||
1009 | |||
1010 | } | ||
1011 | |||
1012 | __attribute__ ((weak)) | ||
1013 | void led_set_kb(uint8_t usb_led) { | ||
1014 | led_set_user(usb_led); | ||
1015 | } | ||
1016 | |||
1017 | __attribute__ ((weak)) | ||
1018 | void led_init_ports(void) | ||
1019 | { | ||
1020 | |||
1021 | } | ||
1022 | |||
1023 | __attribute__ ((weak)) | ||
1024 | void led_set(uint8_t usb_led) | ||
1025 | { | ||
1026 | |||
1027 | // Example LED Code | ||
1028 | // | ||
1029 | // // Using PE6 Caps Lock LED | ||
1030 | // if (usb_led & (1<<USB_LED_CAPS_LOCK)) | ||
1031 | // { | ||
1032 | // // Output high. | ||
1033 | // DDRE |= (1<<6); | ||
1034 | // PORTE |= (1<<6); | ||
1035 | // } | ||
1036 | // else | ||
1037 | // { | ||
1038 | // // Output low. | ||
1039 | // DDRE &= ~(1<<6); | ||
1040 | // PORTE &= ~(1<<6); | ||
1041 | // } | ||
1042 | |||
1043 | led_set_kb(usb_led); | ||
1044 | } | ||
1045 | |||
1046 | |||
701 | //------------------------------------------------------------------------------ | 1047 | //------------------------------------------------------------------------------ |
702 | // Override these functions in your keymap file to play different tunes on | 1048 | // Override these functions in your keymap file to play different tunes on |
703 | // different events such as startup and bootloader jump | 1049 | // different events such as startup and bootloader jump |