diff options
Diffstat (limited to 'keyboards/cannonkeys/stm32f072')
| -rw-r--r-- | keyboards/cannonkeys/stm32f072/keyboard.c | 241 | ||||
| -rw-r--r-- | keyboards/cannonkeys/stm32f072/keyboard.h | 23 | ||||
| -rw-r--r-- | keyboards/cannonkeys/stm32f072/led.c | 251 | ||||
| -rw-r--r-- | keyboards/cannonkeys/stm32f072/led_custom.h | 8 | ||||
| -rw-r--r-- | keyboards/cannonkeys/stm32f072/ws2812.c | 151 |
5 files changed, 0 insertions, 674 deletions
diff --git a/keyboards/cannonkeys/stm32f072/keyboard.c b/keyboards/cannonkeys/stm32f072/keyboard.c deleted file mode 100644 index 39f912506..000000000 --- a/keyboards/cannonkeys/stm32f072/keyboard.c +++ /dev/null | |||
| @@ -1,241 +0,0 @@ | |||
| 1 | #include "keyboard.h" | ||
| 2 | #include "ch.h" | ||
| 3 | #include "hal.h" | ||
| 4 | #include "led_custom.h" | ||
| 5 | #include "util.h" | ||
| 6 | #include "quantum.h" | ||
| 7 | |||
| 8 | #include "raw_hid.h" | ||
| 9 | #include "dynamic_keymap.h" | ||
| 10 | #include "tmk_core/common/eeprom.h" | ||
| 11 | #include "version.h" // for QMK_BUILDDATE used in EEPROM magic | ||
| 12 | |||
| 13 | #include "via.h" | ||
| 14 | #define EEPROM_CUSTOM_BACKLIGHT (VIA_EEPROM_CUSTOM_CONFIG_ADDR) | ||
| 15 | |||
| 16 | backlight_config_t kb_backlight_config = { | ||
| 17 | .enable = true, | ||
| 18 | .breathing = true, | ||
| 19 | .level = BACKLIGHT_LEVELS | ||
| 20 | }; | ||
| 21 | |||
| 22 | void backlight_config_save(){ | ||
| 23 | eeprom_update_byte((uint8_t*)EEPROM_CUSTOM_BACKLIGHT, kb_backlight_config.raw); | ||
| 24 | } | ||
| 25 | |||
| 26 | void backlight_config_load(){ | ||
| 27 | kb_backlight_config.raw = eeprom_read_byte((uint8_t*)EEPROM_CUSTOM_BACKLIGHT); | ||
| 28 | } | ||
| 29 | |||
| 30 | // Called from via_init() if VIA_ENABLE | ||
| 31 | // Called from matrix_init_kb() if not VIA_ENABLE | ||
| 32 | void via_init_kb(void) | ||
| 33 | { | ||
| 34 | // If the EEPROM has the magic, the data is good. | ||
| 35 | // OK to load from EEPROM. | ||
| 36 | if (via_eeprom_is_valid()) { | ||
| 37 | backlight_config_load(); | ||
| 38 | } else { | ||
| 39 | // If the EEPROM has not been saved before, or is out of date, | ||
| 40 | // save the default values to the EEPROM. Default values | ||
| 41 | // come from construction of the backlight_config instance. | ||
| 42 | backlight_config_save(); | ||
| 43 | |||
| 44 | // DO NOT set EEPROM valid here, let caller do this | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | __attribute__ ((weak)) | ||
| 49 | void matrix_init_board(void); | ||
| 50 | |||
| 51 | void matrix_init_kb(void){ | ||
| 52 | // If VIA is disabled, we still need to load backlight settings. | ||
| 53 | // Call via_init_kb() the same way as via_init(), with setting | ||
| 54 | // EEPROM valid afterwards. | ||
| 55 | #ifndef VIA_ENABLE | ||
| 56 | via_init_kb(); | ||
| 57 | via_eeprom_set_valid(true); | ||
| 58 | #endif // VIA_ENABLE | ||
| 59 | backlight_init_ports(); | ||
| 60 | |||
| 61 | matrix_init_board(); | ||
| 62 | } | ||
| 63 | |||
| 64 | bool process_record_kb(uint16_t keycode, keyrecord_t *record) { | ||
| 65 | switch (keycode) { | ||
| 66 | case BL_INC: | ||
| 67 | if (record->event.pressed) { | ||
| 68 | kb_backlight_config.level = kb_backlight_config.level + 1; | ||
| 69 | if(kb_backlight_config.level > BACKLIGHT_LEVELS){ | ||
| 70 | kb_backlight_config.level = BACKLIGHT_LEVELS; | ||
| 71 | } | ||
| 72 | backlight_set(kb_backlight_config.level); | ||
| 73 | backlight_config_save(); | ||
| 74 | } | ||
| 75 | return false; | ||
| 76 | case BL_TOGG: | ||
| 77 | if (record->event.pressed) { | ||
| 78 | kb_backlight_config.enable = !kb_backlight_config.enable; | ||
| 79 | if(kb_backlight_config.enable){ | ||
| 80 | backlight_set(kb_backlight_config.level); | ||
| 81 | } else { | ||
| 82 | backlight_set(0); | ||
| 83 | } | ||
| 84 | backlight_config_save(); | ||
| 85 | } | ||
| 86 | return false; | ||
| 87 | |||
| 88 | case BL_DEC: | ||
| 89 | if (record->event.pressed) { | ||
| 90 | if(kb_backlight_config.level <= 1){ | ||
| 91 | kb_backlight_config.level = 0; | ||
| 92 | } else { | ||
| 93 | kb_backlight_config.level = kb_backlight_config.level - 1; | ||
| 94 | } | ||
| 95 | backlight_set(kb_backlight_config.level); | ||
| 96 | backlight_config_save(); | ||
| 97 | } | ||
| 98 | return false; | ||
| 99 | case BL_BRTG: | ||
| 100 | if (record->event.pressed) { | ||
| 101 | kb_backlight_config.breathing = !kb_backlight_config.breathing; | ||
| 102 | breathing_toggle(); | ||
| 103 | backlight_config_save(); | ||
| 104 | } | ||
| 105 | return false; | ||
| 106 | default: | ||
| 107 | break; | ||
| 108 | } | ||
| 109 | |||
| 110 | return process_record_user(keycode, record);; | ||
| 111 | } | ||
| 112 | |||
| 113 | #ifdef VIA_ENABLE | ||
| 114 | |||
| 115 | void backlight_get_value( uint8_t *data ) | ||
| 116 | { | ||
| 117 | uint8_t *value_id = &(data[0]); | ||
| 118 | uint8_t *value_data = &(data[1]); | ||
| 119 | switch (*value_id) | ||
| 120 | { | ||
| 121 | case id_qmk_backlight_brightness: | ||
| 122 | { | ||
| 123 | // level / BACKLIGHT_LEVELS * 255 | ||
| 124 | value_data[0] = ((uint16_t)kb_backlight_config.level) * 255 / BACKLIGHT_LEVELS; | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | case id_qmk_backlight_effect: | ||
| 128 | { | ||
| 129 | value_data[0] = kb_backlight_config.breathing ? 1 : 0; | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | void backlight_set_value( uint8_t *data ) | ||
| 136 | { | ||
| 137 | uint8_t *value_id = &(data[0]); | ||
| 138 | uint8_t *value_data = &(data[1]); | ||
| 139 | switch (*value_id) | ||
| 140 | { | ||
| 141 | case id_qmk_backlight_brightness: | ||
| 142 | { | ||
| 143 | // level / 255 * BACKLIGHT_LEVELS | ||
| 144 | kb_backlight_config.level = ((uint16_t)value_data[0]) * BACKLIGHT_LEVELS / 255; | ||
| 145 | backlight_set(kb_backlight_config.level); | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | case id_qmk_backlight_effect: | ||
| 149 | { | ||
| 150 | if ( value_data[0] == 0 ) { | ||
| 151 | kb_backlight_config.breathing = false; | ||
| 152 | breathing_disable(); | ||
| 153 | } else { | ||
| 154 | kb_backlight_config.breathing = true; | ||
| 155 | breathing_enable(); | ||
| 156 | } | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | void raw_hid_receive_kb( uint8_t *data, uint8_t length ) | ||
| 163 | { | ||
| 164 | uint8_t *command_id = &(data[0]); | ||
| 165 | uint8_t *command_data = &(data[1]); | ||
| 166 | switch ( *command_id ) | ||
| 167 | { | ||
| 168 | case id_lighting_set_value: | ||
| 169 | { | ||
| 170 | backlight_set_value(command_data); | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | case id_lighting_get_value: | ||
| 174 | { | ||
| 175 | backlight_get_value(command_data); | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | case id_lighting_save: | ||
| 179 | { | ||
| 180 | backlight_config_save(); | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | default: | ||
| 184 | { | ||
| 185 | // Unhandled message. | ||
| 186 | *command_id = id_unhandled; | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | // DO NOT call raw_hid_send(data,length) here, let caller do this | ||
| 191 | } | ||
| 192 | #endif | ||
| 193 | |||
| 194 | // | ||
| 195 | // In the case of VIA being disabled, we still need to check if | ||
| 196 | // keyboard level EEPROM memory is valid before loading. | ||
| 197 | // Thus these are copies of the same functions in VIA, since | ||
| 198 | // the backlight settings reuse VIA's EEPROM magic/version, | ||
| 199 | // and the ones in via.c won't be compiled in. | ||
| 200 | // | ||
| 201 | // Yes, this is sub-optimal, and is only here for completeness | ||
| 202 | // (i.e. catering to the 1% of people that want wilba.tech LED bling | ||
| 203 | // AND want persistent settings BUT DON'T want to use dynamic keymaps/VIA). | ||
| 204 | // | ||
| 205 | #ifndef VIA_ENABLE | ||
| 206 | |||
| 207 | bool via_eeprom_is_valid(void) | ||
| 208 | { | ||
| 209 | char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" | ||
| 210 | uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F ); | ||
| 211 | uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F ); | ||
| 212 | uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F ); | ||
| 213 | |||
| 214 | return (eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0 ) == magic0 && | ||
| 215 | eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1 ) == magic1 && | ||
| 216 | eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2 ) == magic2 ); | ||
| 217 | } | ||
| 218 | |||
| 219 | // Sets VIA/keyboard level usage of EEPROM to valid/invalid | ||
| 220 | // Keyboard level code (eg. via_init_kb()) should not call this | ||
| 221 | void via_eeprom_set_valid(bool valid) | ||
| 222 | { | ||
| 223 | char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" | ||
| 224 | uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F ); | ||
| 225 | uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F ); | ||
| 226 | uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F ); | ||
| 227 | |||
| 228 | eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0, valid ? magic0 : 0xFF); | ||
| 229 | eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1, valid ? magic1 : 0xFF); | ||
| 230 | eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2, valid ? magic2 : 0xFF); | ||
| 231 | } | ||
| 232 | |||
| 233 | void via_eeprom_reset(void) | ||
| 234 | { | ||
| 235 | // Set the VIA specific EEPROM state as invalid. | ||
| 236 | via_eeprom_set_valid(false); | ||
| 237 | // Set the TMK/QMK EEPROM state as invalid. | ||
| 238 | eeconfig_disable(); | ||
| 239 | } | ||
| 240 | |||
| 241 | #endif // VIA_ENABLE | ||
diff --git a/keyboards/cannonkeys/stm32f072/keyboard.h b/keyboards/cannonkeys/stm32f072/keyboard.h deleted file mode 100644 index 81dd1b704..000000000 --- a/keyboards/cannonkeys/stm32f072/keyboard.h +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "quantum.h" | ||
| 4 | |||
| 5 | typedef union { | ||
| 6 | uint8_t raw; | ||
| 7 | struct { | ||
| 8 | bool enable :1; | ||
| 9 | bool breathing : 1; | ||
| 10 | uint8_t level :6; | ||
| 11 | }; | ||
| 12 | } backlight_config_t; | ||
| 13 | |||
| 14 | // Backlighting | ||
| 15 | extern backlight_config_t kb_backlight_config; | ||
| 16 | extern bool kb_backlight_breathing; | ||
| 17 | void backlight_init_ports(void); | ||
| 18 | void backlight_set(uint8_t level); | ||
| 19 | bool is_breathing(void); | ||
| 20 | void breathing_enable(void); | ||
| 21 | void breathing_disable(void); | ||
| 22 | void backlight_config_load(void); | ||
| 23 | void backlight_config_save(void); | ||
diff --git a/keyboards/cannonkeys/stm32f072/led.c b/keyboards/cannonkeys/stm32f072/led.c deleted file mode 100644 index 5c7df47da..000000000 --- a/keyboards/cannonkeys/stm32f072/led.c +++ /dev/null | |||
| @@ -1,251 +0,0 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2012 Jun Wako <wakojun@gmail.com> | ||
| 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 "hal.h" | ||
| 19 | #include "led_custom.h" | ||
| 20 | #include "keyboard.h" | ||
| 21 | #include "printf.h" | ||
| 22 | |||
| 23 | static void breathing_callback(PWMDriver *pwmp); | ||
| 24 | |||
| 25 | static PWMConfig pwmCFG = { | ||
| 26 | 0xFFFF, /* PWM clock frequency */ | ||
| 27 | 256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ | ||
| 28 | NULL, /* No Callback */ | ||
| 29 | { | ||
| 30 | {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */ | ||
| 31 | {PWM_OUTPUT_DISABLED, NULL}, | ||
| 32 | {PWM_OUTPUT_DISABLED, NULL}, | ||
| 33 | {PWM_OUTPUT_DISABLED, NULL} | ||
| 34 | }, | ||
| 35 | 0, /* HW dependent part.*/ | ||
| 36 | 0 | ||
| 37 | }; | ||
| 38 | |||
| 39 | static PWMConfig pwmCFG_breathing = { | ||
| 40 | 0xFFFF, /* 10kHz PWM clock frequency */ | ||
| 41 | 256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ | ||
| 42 | breathing_callback, /* Breathing Callback */ | ||
| 43 | { | ||
| 44 | {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */ | ||
| 45 | {PWM_OUTPUT_DISABLED, NULL}, | ||
| 46 | {PWM_OUTPUT_DISABLED, NULL}, | ||
| 47 | {PWM_OUTPUT_DISABLED, NULL} | ||
| 48 | }, | ||
| 49 | 0, /* HW dependent part.*/ | ||
| 50 | 0 | ||
| 51 | }; | ||
| 52 | |||
| 53 | // See http://jared.geek.nz/2013/feb/linear-led-pwm | ||
| 54 | static uint16_t cie_lightness(uint16_t v) { | ||
| 55 | if (v <= 5243) // if below 8% of max | ||
| 56 | return v / 9; // same as dividing by 900% | ||
| 57 | else { | ||
| 58 | uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare | ||
| 59 | // to get a useful result with integer division, we shift left in the expression above | ||
| 60 | // and revert what we've done again after squaring. | ||
| 61 | y = y * y * y >> 8; | ||
| 62 | if (y > 0xFFFFUL) // prevent overflow | ||
| 63 | return 0xFFFFU; | ||
| 64 | else | ||
| 65 | return (uint16_t) y; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | |||
| 70 | uint8_t get_backlight_level(void){ | ||
| 71 | return kb_backlight_config.level; | ||
| 72 | } | ||
| 73 | |||
| 74 | void backlight_init_ports(void) { | ||
| 75 | printf("backlight_init_ports()\n"); | ||
| 76 | palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(1)); | ||
| 77 | pwmStart(&PWMD3, &pwmCFG); | ||
| 78 | // pwmEnableChannel(&PWMD3, 0, PWM_FRACTION_TO_WIDTH(&PWMD3, 0xFFFF,cie_lightness(0xFFFF))); | ||
| 79 | if(kb_backlight_config.enable){ | ||
| 80 | backlight_set(kb_backlight_config.level); | ||
| 81 | if(kb_backlight_config.breathing){ | ||
| 82 | breathing_enable(); | ||
| 83 | } | ||
| 84 | } else { | ||
| 85 | backlight_set(0); | ||
| 86 | } | ||
| 87 | |||
| 88 | } | ||
| 89 | |||
| 90 | void backlight_set(uint8_t level) { | ||
| 91 | printf("backlight_set(%d)\n", level); | ||
| 92 | uint32_t duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t) level / BACKLIGHT_LEVELS)); | ||
| 93 | printf("duty: (%d)\n", duty); | ||
| 94 | if (level == 0) { | ||
| 95 | // Turn backlight off | ||
| 96 | pwmDisableChannel(&PWMD3, 0); | ||
| 97 | } else { | ||
| 98 | // Turn backlight on | ||
| 99 | if(!is_breathing()){ | ||
| 100 | pwmEnableChannel(&PWMD3, 0, PWM_FRACTION_TO_WIDTH(&PWMD3,0xFFFF,duty)); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | uint8_t backlight_tick = 0; | ||
| 107 | |||
| 108 | void backlight_task(void) { | ||
| 109 | } | ||
| 110 | |||
| 111 | #define BREATHING_NO_HALT 0 | ||
| 112 | #define BREATHING_HALT_OFF 1 | ||
| 113 | #define BREATHING_HALT_ON 2 | ||
| 114 | #define BREATHING_STEPS 128 | ||
| 115 | |||
| 116 | static uint8_t breathing_period = BREATHING_PERIOD; | ||
| 117 | static uint8_t breathing_halt = BREATHING_NO_HALT; | ||
| 118 | static uint16_t breathing_counter = 0; | ||
| 119 | |||
| 120 | bool is_breathing(void) { | ||
| 121 | return PWMD3.config == &pwmCFG_breathing; | ||
| 122 | } | ||
| 123 | |||
| 124 | #define breathing_min() do {breathing_counter = 0;} while (0) | ||
| 125 | #define breathing_max() do {breathing_counter = breathing_period * 256 / 2;} while (0) | ||
| 126 | |||
| 127 | |||
| 128 | void breathing_interrupt_enable(void){ | ||
| 129 | pwmStop(&PWMD3); | ||
| 130 | pwmStart(&PWMD3, &pwmCFG_breathing); | ||
| 131 | chSysLockFromISR(); | ||
| 132 | pwmEnablePeriodicNotification(&PWMD3); | ||
| 133 | pwmEnableChannelI( | ||
| 134 | &PWMD3, | ||
| 135 | 0, | ||
| 136 | PWM_FRACTION_TO_WIDTH( | ||
| 137 | &PWMD3, | ||
| 138 | 0xFFFF, | ||
| 139 | 0xFFFF | ||
| 140 | ) | ||
| 141 | ); | ||
| 142 | chSysUnlockFromISR(); | ||
| 143 | } | ||
| 144 | |||
| 145 | void breathing_interrupt_disable(void){ | ||
| 146 | pwmStop(&PWMD3); | ||
| 147 | pwmStart(&PWMD3, &pwmCFG); | ||
| 148 | } | ||
| 149 | |||
| 150 | void breathing_enable(void) | ||
| 151 | { | ||
| 152 | breathing_counter = 0; | ||
| 153 | breathing_halt = BREATHING_NO_HALT; | ||
| 154 | breathing_interrupt_enable(); | ||
| 155 | } | ||
| 156 | |||
| 157 | void breathing_pulse(void) | ||
| 158 | { | ||
| 159 | if (get_backlight_level() == 0) | ||
| 160 | breathing_min(); | ||
| 161 | else | ||
| 162 | breathing_max(); | ||
| 163 | breathing_halt = BREATHING_HALT_ON; | ||
| 164 | breathing_interrupt_enable(); | ||
| 165 | } | ||
| 166 | |||
| 167 | void breathing_disable(void) | ||
| 168 | { | ||
| 169 | printf("breathing_disable()\n"); | ||
| 170 | breathing_interrupt_disable(); | ||
| 171 | // Restore backlight level | ||
| 172 | backlight_set(get_backlight_level()); | ||
| 173 | } | ||
| 174 | |||
| 175 | void breathing_self_disable(void) | ||
| 176 | { | ||
| 177 | if (get_backlight_level() == 0) | ||
| 178 | breathing_halt = BREATHING_HALT_OFF; | ||
| 179 | else | ||
| 180 | breathing_halt = BREATHING_HALT_ON; | ||
| 181 | } | ||
| 182 | |||
| 183 | void breathing_toggle(void) { | ||
| 184 | if (is_breathing()){ | ||
| 185 | printf("disable breathing\n"); | ||
| 186 | breathing_disable(); | ||
| 187 | } else { | ||
| 188 | printf("enable breathing\n"); | ||
| 189 | breathing_enable(); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | void breathing_period_set(uint8_t value) | ||
| 194 | { | ||
| 195 | if (!value) | ||
| 196 | value = 1; | ||
| 197 | breathing_period = value; | ||
| 198 | } | ||
| 199 | |||
| 200 | void breathing_period_default(void) { | ||
| 201 | breathing_period_set(BREATHING_PERIOD); | ||
| 202 | } | ||
| 203 | |||
| 204 | void breathing_period_inc(void) | ||
| 205 | { | ||
| 206 | breathing_period_set(breathing_period+1); | ||
| 207 | } | ||
| 208 | |||
| 209 | void breathing_period_dec(void) | ||
| 210 | { | ||
| 211 | breathing_period_set(breathing_period-1); | ||
| 212 | } | ||
| 213 | |||
| 214 | /* To generate breathing curve in python: | ||
| 215 | * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] | ||
| 216 | */ | ||
| 217 | static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 218 | |||
| 219 | // Use this before the cie_lightness function. | ||
| 220 | static inline uint16_t scale_backlight(uint16_t v) { | ||
| 221 | return v / BACKLIGHT_LEVELS * get_backlight_level(); | ||
| 222 | } | ||
| 223 | |||
| 224 | static void breathing_callback(PWMDriver *pwmp) | ||
| 225 | { | ||
| 226 | (void)pwmp; | ||
| 227 | uint16_t interval = (uint16_t) breathing_period * 256 / BREATHING_STEPS; | ||
| 228 | // resetting after one period to prevent ugly reset at overflow. | ||
| 229 | breathing_counter = (breathing_counter + 1) % (breathing_period * 256); | ||
| 230 | uint8_t index = breathing_counter / interval % BREATHING_STEPS; | ||
| 231 | |||
| 232 | if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || | ||
| 233 | ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) | ||
| 234 | { | ||
| 235 | breathing_interrupt_disable(); | ||
| 236 | } | ||
| 237 | |||
| 238 | uint32_t duty = cie_lightness(scale_backlight(breathing_table[index] * 256)); | ||
| 239 | |||
| 240 | chSysLockFromISR(); | ||
| 241 | pwmEnableChannelI( | ||
| 242 | &PWMD3, | ||
| 243 | 0, | ||
| 244 | PWM_FRACTION_TO_WIDTH( | ||
| 245 | &PWMD3, | ||
| 246 | 0xFFFF, | ||
| 247 | duty | ||
| 248 | ) | ||
| 249 | ); | ||
| 250 | chSysUnlockFromISR(); | ||
| 251 | } | ||
diff --git a/keyboards/cannonkeys/stm32f072/led_custom.h b/keyboards/cannonkeys/stm32f072/led_custom.h deleted file mode 100644 index 550d5b84c..000000000 --- a/keyboards/cannonkeys/stm32f072/led_custom.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | void backlight_task(void); | ||
| 4 | void breathing_interrupt_disable(void); | ||
| 5 | void breathing_interrupt_enable(void); | ||
| 6 | void breathing_toggle(void); | ||
| 7 | void breathing_enable(void); | ||
| 8 | void breathing_disable(void); | ||
diff --git a/keyboards/cannonkeys/stm32f072/ws2812.c b/keyboards/cannonkeys/stm32f072/ws2812.c deleted file mode 100644 index b2f2384f2..000000000 --- a/keyboards/cannonkeys/stm32f072/ws2812.c +++ /dev/null | |||
| @@ -1,151 +0,0 @@ | |||
| 1 | #include "ch.h" | ||
| 2 | #include "hal.h" | ||
| 3 | |||
| 4 | #include "ws2812.h" | ||
| 5 | |||
| 6 | #define BYTES_FOR_LED_BYTE 4 | ||
| 7 | #define NB_COLORS 3 | ||
| 8 | #define BYTES_FOR_LED BYTES_FOR_LED_BYTE*NB_COLORS | ||
| 9 | #define DATA_SIZE BYTES_FOR_LED*NB_LEDS | ||
| 10 | #define RESET_SIZE 200 | ||
| 11 | |||
| 12 | // Define the spi your LEDs are plugged to here | ||
| 13 | #define LEDS_SPI WS2812_SPI | ||
| 14 | // Define the number of LEDs you wish to control in your LED strip | ||
| 15 | #define NB_LEDS RGBLED_NUM | ||
| 16 | |||
| 17 | #define LED_SPIRAL 0 | ||
| 18 | |||
| 19 | static uint8_t txbuf[DATA_SIZE + RESET_SIZE]; | ||
| 20 | static uint8_t get_protocol_eq(uint8_t data, int pos); | ||
| 21 | |||
| 22 | /* | ||
| 23 | * This lib is meant to be used asynchronously, thus the colors contained in | ||
| 24 | * the txbuf will be sent in loop, so that the colors are always the ones you | ||
| 25 | * put in the table (the user thus have less to worry about) | ||
| 26 | * | ||
| 27 | * Since the data are sent via DMA, and the call to spiSend is a blocking one, | ||
| 28 | * the processor ressources are not used to much, if you see your program being | ||
| 29 | * too slow, simply add a: | ||
| 30 | * chThdSleepMilliseconds(x); | ||
| 31 | * after the spiSend, where you increment x untill you are satisfied with your | ||
| 32 | * program speed, another trick may be to lower this thread priority : your call | ||
| 33 | */ | ||
| 34 | static THD_WORKING_AREA(LEDS_THREAD_WA, 128); | ||
| 35 | static THD_FUNCTION(ledsThread, arg) { | ||
| 36 | (void) arg; | ||
| 37 | while(1){ | ||
| 38 | spiSend(&LEDS_SPI, DATA_SIZE + RESET_SIZE, txbuf); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | #if LED_SPIRAL | ||
| 43 | /* | ||
| 44 | * 'Led spiral' is a simple demo in which we put all the leds to the same | ||
| 45 | * color, where this color does all the hsv circle in loop. | ||
| 46 | * If you want to launch the thread that will chage the led colors to the | ||
| 47 | * appropriate value, simply set LED_SPIRAL to 1. | ||
| 48 | */ | ||
| 49 | |||
| 50 | static THD_WORKING_AREA(HSVTRANS_WA, 128); | ||
| 51 | static THD_FUNCTION(hsv_transThread, arg) { | ||
| 52 | (void) arg; | ||
| 53 | hsv_color color = {0, 255, 255}; | ||
| 54 | while(1){ | ||
| 55 | color.h += 1; | ||
| 56 | color.h %= 256; | ||
| 57 | set_leds_color_hsv(color); | ||
| 58 | chThdSleepMilliseconds(50); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | #endif | ||
| 62 | |||
| 63 | static const SPIConfig spicfg = { | ||
| 64 | false, | ||
| 65 | NULL, | ||
| 66 | GPIOB, | ||
| 67 | 15, | ||
| 68 | SPI_CR1_BR_1|SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us | ||
| 69 | }; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Function used to initialize the driver. | ||
| 73 | * | ||
| 74 | * Starts by shutting off all the LEDs. | ||
| 75 | * Then gets access on the LED_SPI driver. | ||
| 76 | * May eventually launch an animation on the LEDs (e.g. a thread setting the | ||
| 77 | * txbuff values) | ||
| 78 | */ | ||
| 79 | void leds_init(void){ | ||
| 80 | for(int i = 0; i < RESET_SIZE; i++) | ||
| 81 | txbuf[DATA_SIZE+i] = 0x00; | ||
| 82 | spiAcquireBus(&LEDS_SPI); /* Acquire ownership of the bus. */ | ||
| 83 | spiStart(&LEDS_SPI, &spicfg); /* Setup transfer parameters. */ | ||
| 84 | spiSelect(&LEDS_SPI); /* Slave Select assertion. */ | ||
| 85 | chThdCreateStatic(LEDS_THREAD_WA, sizeof(LEDS_THREAD_WA),NORMALPRIO, ledsThread, NULL); | ||
| 86 | #if LED_SPIRAL | ||
| 87 | chThdCreateStatic(HSVTRANS_WA, sizeof(HSVTRANS_WA), | ||
| 88 | NORMALPRIO, hsv_transThread, NULL); | ||
| 89 | #endif | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to | ||
| 94 | * the ws2812b protocol, we use this helper function to translate bytes into | ||
| 95 | * 0s and 1s for the LED (with the appropriate timing). | ||
| 96 | */ | ||
| 97 | static uint8_t get_protocol_eq(uint8_t data, int pos){ | ||
| 98 | uint8_t eq = 0; | ||
| 99 | if (data & (1 << (2*(3-pos)))) | ||
| 100 | eq = 0b1110; | ||
| 101 | else | ||
| 102 | eq = 0b1000; | ||
| 103 | if (data & (2 << (2*(3-pos)))) | ||
| 104 | eq += 0b11100000; | ||
| 105 | else | ||
| 106 | eq += 0b10000000; | ||
| 107 | return eq; | ||
| 108 | } | ||
| 109 | |||
| 110 | // | ||
| 111 | ///* | ||
| 112 | // * If you want to set a LED's color in the RGB color space, simply call this | ||
| 113 | // * function with a hsv_color containing the desired color and the index of the | ||
| 114 | // * led on the LED strip (starting from 0, the first one being the closest the | ||
| 115 | // * first plugged to the board) | ||
| 116 | // * | ||
| 117 | // * Only set the color of the LEDs through the functions given by this API | ||
| 118 | // * (unless you really know what you are doing) | ||
| 119 | // */ | ||
| 120 | void set_led_color_rgb(LED_TYPE color, int pos){ | ||
| 121 | for(int j = 0; j < 4; j++) | ||
| 122 | txbuf[BYTES_FOR_LED*pos + j] = get_protocol_eq(color.g, j); | ||
| 123 | for(int j = 0; j < 4; j++) | ||
| 124 | txbuf[BYTES_FOR_LED*pos + BYTES_FOR_LED_BYTE+j] = get_protocol_eq(color.r, j); | ||
| 125 | for(int j = 0; j < 4; j++) | ||
| 126 | txbuf[BYTES_FOR_LED*pos + BYTES_FOR_LED_BYTE*2+j] = get_protocol_eq(color.b, j); | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | void WS2812_init(void) { | ||
| 131 | leds_init(); | ||
| 132 | } | ||
| 133 | |||
| 134 | void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { | ||
| 135 | uint8_t i = 0; | ||
| 136 | while (i < number_of_leds) { | ||
| 137 | set_led_color_rgb(ledarray[i], i); | ||
| 138 | i++; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | |||
| 143 | void set_leds_color_rgb(LED_TYPE color){ | ||
| 144 | for(int i = 0; i < NB_LEDS; i++) | ||
| 145 | set_led_color_rgb(color, i); | ||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds) { | ||
| 150 | |||
| 151 | } | ||
