Enable PWM Support for Planck EZ Indicator Lights (#6473)
* remove led layer code * enable PWM on STM32F303 * Unusable PWM code * Updated PWM Stuff? * PWM Semi-working * Both LEDs working at the same time * Update names * Add led level functions * Add LED levels and persistent settings * Revert change due to issues with timing related code * Review feedback and minor cleanup
This commit is contained in:
		
							parent
							
								
									5004562441
								
							
						
					
					
						commit
						547fbe769c
					
				
					 4 changed files with 164 additions and 30 deletions
				
			
		|  | @ -14,6 +14,10 @@ | |||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #include "ez.h" | ||||
| #include "ch.h" | ||||
| #include "hal.h" | ||||
|  keyboard_config_t keyboard_config; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef RGB_MATRIX_ENABLE | ||||
| const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { | ||||
|  | @ -112,39 +116,148 @@ void suspend_power_down_kb(void) { | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| void matrix_init_kb(void) { | ||||
|   matrix_init_user(); | ||||
| /* Left B9   Right B8 */ | ||||
| 
 | ||||
|   palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL); | ||||
|   palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL); | ||||
| 
 | ||||
|   palClearPad(GPIOB, 8); | ||||
|   palClearPad(GPIOB, 9); | ||||
| // See http://jared.geek.nz/2013/feb/linear-led-pwm
 | ||||
| static uint16_t cie_lightness(uint16_t v) { | ||||
|   if (v <= 5243) // if below 8% of max
 | ||||
|     return v / 9; // same as dividing by 900%
 | ||||
|   else { | ||||
|     uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
 | ||||
|     // to get a useful result with integer division, we shift left in the expression above
 | ||||
|     // and revert what we've done again after squaring.
 | ||||
|     y = y * y * y >> 8; | ||||
|     if (y > 0xFFFFUL) // prevent overflow
 | ||||
|       return 0xFFFFU; | ||||
|     else | ||||
|       return (uint16_t) y; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void matrix_scan_kb(void) { | ||||
|   matrix_scan_user(); | ||||
| static PWMConfig pwmCFG = { | ||||
|     0xFFFF,/* PWM clock frequency  */ | ||||
|     256,/* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ | ||||
|     NULL, | ||||
|     { | ||||
|         {PWM_OUTPUT_DISABLED, NULL}, /* channel 0 -> TIM1-CH1 = PA8 */ | ||||
|         {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIM1-CH2 = PA9 */ | ||||
|         {PWM_OUTPUT_ACTIVE_HIGH, NULL}, | ||||
|         {PWM_OUTPUT_ACTIVE_HIGH, NULL} | ||||
|     }, | ||||
|     0, /* HW dependent part.*/ | ||||
|     0 | ||||
| }; | ||||
| 
 | ||||
| static uint32_t planck_ez_right_led_duty; | ||||
| static uint32_t planck_ez_left_led_duty; | ||||
| 
 | ||||
| void planck_ez_right_led_level(uint8_t level) { | ||||
|     planck_ez_right_led_duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t) level / 255)); | ||||
|     if (level == 0) { | ||||
|         // Turn backlight off
 | ||||
|         pwmDisableChannel(&PWMD4, 2); | ||||
|     } else { | ||||
|         // Turn backlight on
 | ||||
|         pwmEnableChannel(&PWMD4, 2, PWM_FRACTION_TO_WIDTH(&PWMD4,0xFFFF,planck_ez_right_led_duty)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint32_t layer_state_set_kb(uint32_t state) { | ||||
| 
 | ||||
|   palClearPad(GPIOB, 8); | ||||
|   palClearPad(GPIOB, 9); | ||||
| void planck_ez_right_led_on(void){ | ||||
|     pwmEnableChannel(&PWMD4, 2, PWM_FRACTION_TO_WIDTH(&PWMD4,0xFFFF,planck_ez_right_led_duty)); | ||||
| } | ||||
| 
 | ||||
| void planck_ez_right_led_off(void){ | ||||
|     pwmDisableChannel(&PWMD4, 2); | ||||
| } | ||||
| 
 | ||||
| void planck_ez_left_led_level(uint8_t level) { | ||||
|     planck_ez_left_led_duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t) level / 255)); | ||||
|     if (level == 0) { | ||||
|         // Turn backlight off
 | ||||
|         pwmDisableChannel(&PWMD4, 3); | ||||
|     } else { | ||||
|         // Turn backlight on
 | ||||
|         pwmEnableChannel(&PWMD4, 3, PWM_FRACTION_TO_WIDTH(&PWMD4,0xFFFF,planck_ez_left_led_duty)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void planck_ez_left_led_on(void){ | ||||
|     pwmEnableChannel(&PWMD4, 3, PWM_FRACTION_TO_WIDTH(&PWMD4,0xFFFF,planck_ez_left_led_duty)); | ||||
| } | ||||
| 
 | ||||
| void planck_ez_left_led_off(void){ | ||||
|     pwmDisableChannel(&PWMD4, 3); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void led_initialize_hardware(void) { | ||||
|     pwmStart(&PWMD4, &pwmCFG); | ||||
| 
 | ||||
|     // set up defaults
 | ||||
|     planck_ez_right_led_level((uint8_t)keyboard_config.led_level * 255 / 4 ); | ||||
|     palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(2)); | ||||
|     planck_ez_left_led_level((uint8_t)keyboard_config.led_level * 255 / 4 ); | ||||
|     palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(2)); | ||||
| 
 | ||||
| 
 | ||||
|     // turn LEDs off by default
 | ||||
|     planck_ez_left_led_off(); | ||||
|     planck_ez_right_led_off(); | ||||
| } | ||||
| 
 | ||||
| void keyboard_pre_init_kb(void) { | ||||
|     // read kb settings from eeprom
 | ||||
|     keyboard_config.raw = eeconfig_read_kb(); | ||||
| 
 | ||||
|     // initialize settings for front LEDs
 | ||||
|     led_initialize_hardware(); | ||||
| } | ||||
| 
 | ||||
| void eeconfig_init_kb(void) {  // EEPROM is getting reset!
 | ||||
|     keyboard_config.raw = 0; | ||||
|     keyboard_config.led_level = 4; | ||||
|     eeconfig_update_kb(keyboard_config.raw); | ||||
|     eeconfig_init_user(); | ||||
| } | ||||
| 
 | ||||
| layer_state_t layer_state_set_kb(layer_state_t state) { | ||||
|     planck_ez_left_led_off(); | ||||
|     planck_ez_right_led_off(); | ||||
|     state = layer_state_set_user(state); | ||||
|     uint8_t layer = biton32(state); | ||||
|     switch (layer) { | ||||
|         case 3: | ||||
|         palSetPad(GPIOB, 9); | ||||
|             planck_ez_left_led_on(); | ||||
|             break; | ||||
|         case 4: | ||||
|         palSetPad(GPIOB, 8); | ||||
|             planck_ez_right_led_on(); | ||||
|             break; | ||||
|         case 6: | ||||
|         palSetPad(GPIOB, 9); | ||||
|         palSetPad(GPIOB, 8); | ||||
|             planck_ez_right_led_on(); | ||||
|             planck_ez_left_led_on(); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool process_record_kb(uint16_t keycode, keyrecord_t *record) { | ||||
|     switch (keycode) { | ||||
|         case LED_LEVEL: | ||||
|             if (record->event.pressed) { | ||||
|                  keyboard_config.led_level++; | ||||
|                  if (keyboard_config.led_level > 4) { | ||||
|                     keyboard_config.led_level = 0; | ||||
|                  } | ||||
|                  planck_ez_right_led_level((uint8_t)keyboard_config.led_level * 255 / 4 ); | ||||
|                  planck_ez_left_led_level((uint8_t)keyboard_config.led_level * 255 / 4 ); | ||||
|                  eeconfig_update_kb(keyboard_config.raw); | ||||
|                  layer_state_set_kb(layer_state); | ||||
|             } | ||||
|             break; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  |  | |||
|  | @ -50,3 +50,24 @@ LAYOUT_planck_1x2uC( \ | |||
| #define KEYMAP LAYOUT_ortho_4x12 | ||||
| #define LAYOUT_planck_mit LAYOUT_planck_1x2uC | ||||
| #define LAYOUT_planck_grid LAYOUT_ortho_4x12 | ||||
| 
 | ||||
| void planck_ez_right_led_on(void); | ||||
| void planck_ez_right_led_off(void); | ||||
| void planck_ez_right_led_level(uint8_t level); | ||||
| void planck_ez_left_led_on(void); | ||||
| void planck_ez_left_led_off(void); | ||||
| void planck_ez_left_led_level(uint8_t level); | ||||
| 
 | ||||
| enum planck_ez_keycodes { | ||||
|     LED_LEVEL = SAFE_RANGE, | ||||
|     EZ_SAFE_RANGE, | ||||
| }; | ||||
| 
 | ||||
| typedef union { | ||||
|   uint32_t raw; | ||||
|   struct { | ||||
|     uint8_t    led_level :3; | ||||
|   }; | ||||
| } keyboard_config_t; | ||||
| 
 | ||||
| extern keyboard_config_t keyboard_config; | ||||
|  |  | |||
|  | @ -111,7 +111,7 @@ | |||
|  * @brief   Enables the PWM subsystem. | ||||
|  */ | ||||
| #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) | ||||
| #define HAL_USE_PWM                 FALSE | ||||
| #define HAL_USE_PWM                 TRUE | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -183,9 +183,9 @@ | |||
|  */ | ||||
| #define STM32_PWM_USE_ADVANCED              FALSE | ||||
| #define STM32_PWM_USE_TIM1                  FALSE | ||||
| #define STM32_PWM_USE_TIM2                  TRUE | ||||
| #define STM32_PWM_USE_TIM2                  FALSE | ||||
| #define STM32_PWM_USE_TIM3                  TRUE | ||||
| #define STM32_PWM_USE_TIM4                  FALSE | ||||
| #define STM32_PWM_USE_TIM4                  TRUE | ||||
| #define STM32_PWM_USE_TIM8                  FALSE | ||||
| #define STM32_PWM_TIM1_IRQ_PRIORITY         7 | ||||
| #define STM32_PWM_TIM2_IRQ_PRIORITY         7 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Drashna Jaelre
						Drashna Jaelre