aboutsummaryrefslogtreecommitdiff
path: root/quantum/quantum.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/quantum.c')
-rw-r--r--quantum/quantum.c346
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
657void matrix_init_quantum() { 657void 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
708static 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))
724void 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))
756void 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
790static uint8_t breath_intensity;
791static uint8_t breath_speed;
792static uint16_t breathing_index;
793static uint8_t breathing_halt;
794
795void 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
813void 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
831void breathing_disable(void)
832{
833 // Disable breathing interrupt
834 TIMSK1 &= ~_BV(OCIE1A);
835 backlight_set(get_backlight_level());
836}
837
838void 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
852void 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
879bool is_breathing(void)
880{
881 return (TIMSK1 && _BV(OCIE1A));
882}
883
884void 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
890void breathing_intensity_set(uint8_t value)
891{
892 breath_intensity = value;
893}
894
895void breathing_speed_default(void)
896{
897 breath_speed = 4;
898}
899
900void 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
924void 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
936void 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
948void 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 */
961static 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,
964255, 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
968ISR(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))
992void backlight_init_ports(void)
993{
994
995}
996
997__attribute__ ((weak))
998void backlight_set(uint8_t level)
999{
1000
1001}
1002
1003#endif // backlight
1004
1005
1006
1007__attribute__ ((weak))
1008void led_set_user(uint8_t usb_led) {
1009
1010}
1011
1012__attribute__ ((weak))
1013void led_set_kb(uint8_t usb_led) {
1014 led_set_user(usb_led);
1015}
1016
1017__attribute__ ((weak))
1018void led_init_ports(void)
1019{
1020
1021}
1022
1023__attribute__ ((weak))
1024void 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