Skip to content

Commit

Permalink
Enable PWM support for Planck EZ Indicator LEDs
Browse files Browse the repository at this point in the history
  • Loading branch information
drashna authored and fdidron committed Aug 5, 2019
1 parent 4a5b36e commit d2100ba
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 32 deletions.
167 changes: 139 additions & 28 deletions keyboards/planck/ez/ez.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
* 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

#ifdef RGB_MATRIX_ENABLE
void suspend_power_down_kb(void) {
rgb_matrix_set_suspend_state(true);
suspend_power_down_user();
Expand Down Expand Up @@ -114,43 +118,150 @@ led_config_t g_led_config = { {
#endif


void matrix_init_kb(void) {
matrix_init_user();
// 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;
}
}

palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL);
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
};

palClearPad(GPIOB, 8);
palClearPad(GPIOB, 9);
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));
}
}

void matrix_scan_kb(void) {
matrix_scan_user();

void planck_ez_right_led_on(void){
pwmEnableChannel(&PWMD4, 2, PWM_FRACTION_TO_WIDTH(&PWMD4,0xFFFF,planck_ez_right_led_duty));
}

layer_state_t layer_state_set_kb(layer_state_t state) {

palClearPad(GPIOB, 8);
palClearPad(GPIOB, 9);
state = layer_state_set_user(state);
uint8_t layer = biton32(state);
switch (layer) {
case 3:
palSetPad(GPIOB, 9);
break;
case 4:
palSetPad(GPIOB, 8);
break;
case 6:
palSetPad(GPIOB, 9);
palSetPad(GPIOB, 8);
break;
default:
break;
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();
}


uint32_t layer_state_set_kb(uint32_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:
planck_ez_left_led_on();
break;
case 4:
planck_ez_right_led_on();
break;
case 6:
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 process_record_user(keycode, record);
}

#ifdef AUDIO_ENABLE
bool music_mask_kb(uint16_t keycode) {
switch (keycode) {
Expand Down
21 changes: 21 additions & 0 deletions keyboards/planck/ez/ez.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
4 changes: 2 additions & 2 deletions quantum/stm32/chconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 100000
#define CH_CFG_ST_FREQUENCY 1000

/**
* @brief Time delta constant for the tick-less mode.
Expand All @@ -58,7 +58,7 @@
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#define CH_CFG_ST_TIMEDELTA 2
#define CH_CFG_ST_TIMEDELTA 0

/** @} */

Expand Down
2 changes: 1 addition & 1 deletion quantum/stm32/halconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down
2 changes: 1 addition & 1 deletion quantum/stm32/mcuconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 TRUE
#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
Expand Down

0 comments on commit d2100ba

Please sign in to comment.