diff options
-rw-r--r-- | drivers/avr/ws2812.c | 4 | ||||
-rw-r--r-- | keyboards/handwired/practice60/bootloader_defs.h | 2 | ||||
-rw-r--r-- | keyboards/handwired/practice60/config.h | 13 | ||||
-rw-r--r-- | keyboards/handwired/practice60/halconf.h | 2 | ||||
-rw-r--r-- | keyboards/handwired/practice60/hsv2rgb.c | 80 | ||||
-rw-r--r-- | keyboards/handwired/practice60/hsv2rgb.h | 23 | ||||
-rw-r--r-- | keyboards/handwired/practice60/keymaps/default/keymap.c | 6 | ||||
-rw-r--r-- | keyboards/handwired/practice60/led.c | 220 | ||||
-rw-r--r-- | keyboards/handwired/practice60/led_custom.h | 6 | ||||
-rw-r--r-- | keyboards/handwired/practice60/mcuconf.h | 2 | ||||
-rw-r--r-- | keyboards/handwired/practice60/practice60.c | 15 | ||||
-rw-r--r-- | keyboards/handwired/practice60/rules.mk | 4 | ||||
-rw-r--r-- | keyboards/handwired/practice60/underglow.h | 10 | ||||
-rw-r--r-- | keyboards/handwired/practice60/ws2812.c (renamed from keyboards/handwired/practice60/underglow.c) | 113 | ||||
-rw-r--r-- | keyboards/handwired/practice60/ws2812.h | 20 | ||||
-rw-r--r-- | quantum/rgblight.c | 11 | ||||
-rwxr-xr-x | tmk_core/common/chibios/eeprom_stm32.c | 17 |
17 files changed, 328 insertions, 220 deletions
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c index 59e032bf71..5bd837ec75 100644 --- a/drivers/avr/ws2812.c +++ b/drivers/avr/ws2812.c @@ -128,11 +128,11 @@ unsigned char I2C_Write(unsigned char c) c <<= 1; } - + I2C_WriteBit(0); _delay_us(I2C_DELAY); _delay_us(I2C_DELAY); - + // _delay_us(I2C_DELAY); //return I2C_ReadBit(); return 0; diff --git a/keyboards/handwired/practice60/bootloader_defs.h b/keyboards/handwired/practice60/bootloader_defs.h index 0f45203cb6..6b8fa9f727 100644 --- a/keyboards/handwired/practice60/bootloader_defs.h +++ b/keyboards/handwired/practice60/bootloader_defs.h @@ -7,4 +7,4 @@ // STM32F103* does NOT have an USB bootloader in ROM (only serial), // so setting anything here does not make much sense -// #define STM32_BOOTLOADER_ADDRESS 0x1FFFC800 +#define STM32_BOOTLOADER_ADDRESS 0x80000000 diff --git a/keyboards/handwired/practice60/config.h b/keyboards/handwired/practice60/config.h index 648dd62edc..c015bb7465 100644 --- a/keyboards/handwired/practice60/config.h +++ b/keyboards/handwired/practice60/config.h @@ -35,7 +35,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MATRIX_ROW_PINS { B3, B4, B5, B6, B7 } #define DIODE_DIRECTION COL2ROW -#define BACKLIGHT_LEVELS 1 +#define BACKLIGHT_LEVELS 6 +#define BACKLIGHT_BREATHING +#define BREATHING_PERIOD 6 /* define if matrix has ghost */ //#define MATRIX_HAS_GHOST @@ -48,6 +50,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* Locking resynchronize hack */ #define LOCKING_RESYNC_ENABLE +#define RGBLIGHT_ANIMATIONS + +#define WS2812_LED_N 9 +#define RGBLED_NUM WS2812_LED_N +#define PORT_WS2812 GPIOB +#define PIN_WS2812 15 +#define WS2812_SPI SPID2 + + /* * Feature disable options * These options are also useful to firmware size reduction. diff --git a/keyboards/handwired/practice60/halconf.h b/keyboards/handwired/practice60/halconf.h index 5fba285a38..72879a575b 100644 --- a/keyboards/handwired/practice60/halconf.h +++ b/keyboards/handwired/practice60/halconf.h @@ -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 /** diff --git a/keyboards/handwired/practice60/hsv2rgb.c b/keyboards/handwired/practice60/hsv2rgb.c deleted file mode 100644 index adb7af8fa5..0000000000 --- a/keyboards/handwired/practice60/hsv2rgb.c +++ /dev/null @@ -1,80 +0,0 @@ -/* hsv2rgb.c - * Integer only conversion functions between HSV and RGB - */ - -#include "hsv2rgb.h" - -// TODO fix these buggy macros -#define max(x,y) ((x>y) ? x:y) -#define min(x,y) ((x>y) ? y:x) -#define min3(x,y,z) (min(min(x,y),z)) -#define max3(x,y,z) (max(max(x,y),z)) - - -rgb_color hsv2rgb(hsv_color hsv) -{ - // From : http://qscribble.blogspot.fr/2008/06/integer-conversion-from-hsl-to-rgb.html - int h = hsv.h; - int s = hsv.s; - int v = hsv.v; - rgb_color rgb = {0, 0, 0}; - - if (v == 0) - return rgb; - - // sextant = 0 .. 5 - int sextant = (h*6)/256; - // f = 0 .. 42 - int f = h - (sextant*256)/6; - - int p = (v * (256 - s))/256; - int q = (v * (256*43 - s*f))/(256*43); - int t = (v * (256*43 - s*(43-f)))/(256*43); - - // Corrige les erreurs dues aux arrondis - p = max(min(p, 255), 0); - q = max(min(q, 255), 0); - t = max(min(t, 255), 0); - - switch(sextant){ - case 0: rgb.r = v; rgb.g = t; rgb.b = p; break; - case 1: rgb.r = q; rgb.g = v; rgb.b = p; break; - case 2: rgb.r = p; rgb.g = v; rgb.b = t; break; - case 3: rgb.r = p; rgb.g = q; rgb.b = v; break; - case 4: rgb.r = t; rgb.g = p; rgb.b = v; break; - default:rgb.r = v; rgb.g = p; rgb.b = q; break; - } - return rgb; -} - - -hsv_color rgb2hsv(rgb_color rgb) -{ - // From : http://www.ruinelli.ch/rgb-to-hsv - hsv_color hsv = {0, 0, 0}; - int min, max, delta; - - min = min3(rgb.r, rgb.g, rgb.b); - max = max3(rgb.r, rgb.g, rgb.b); - - if(max==0) { - hsv.h = 0; - hsv.s = 0; - hsv.v = 0; - return hsv; - } - - hsv.v = max; - delta = max - min; - - hsv.s = (delta)*255 / max; - - if(rgb.r == max) - hsv.h = (rgb.g - rgb.b)*42/delta; // between yellow & magenta - else if(rgb.g == max) - hsv.h = 120 + (rgb.b - rgb.r)*42/delta; // between cyan & yellow - else - hsv.h = 240 + (rgb.r - rgb.g)*42/delta; // between magenta & cyan - - return hsv; -}
\ No newline at end of file diff --git a/keyboards/handwired/practice60/hsv2rgb.h b/keyboards/handwired/practice60/hsv2rgb.h deleted file mode 100644 index 99566c32c0..0000000000 --- a/keyboards/handwired/practice60/hsv2rgb.h +++ /dev/null @@ -1,23 +0,0 @@ -/* hsv2rgb.h - * Convert Hue Saturation Value to Red Green Blue - * - * Programme de convertion d'une information HSV en RGB - */ -#ifndef HSV2RGB_H -#define HSV2RGB_H - -typedef struct { - unsigned char h; - unsigned char s; - unsigned char v; -} hsv_color; - -typedef struct { - unsigned char r; - unsigned char g; - unsigned char b; -} rgb_color; - -rgb_color hsv2rgb(hsv_color hsv); - -#endif
\ No newline at end of file diff --git a/keyboards/handwired/practice60/keymaps/default/keymap.c b/keyboards/handwired/practice60/keymaps/default/keymap.c index ac6e755097..66ebe0646d 100644 --- a/keyboards/handwired/practice60/keymaps/default/keymap.c +++ b/keyboards/handwired/practice60/keymaps/default/keymap.c @@ -32,16 +32,16 @@ enum custom_keycodes { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_BASE] = LAYOUT_60_ansi( KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \ - KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MT(MOD_LSFT, KC_Y), KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(_FN1), KC_RCTL ), [_FN1] = LAYOUT_60_ansi( - KC_GESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC, \ + KC_GESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \ RGB_TOG, RGB_MOD, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ - _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ + BL_BRTG, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ BL_INC, BL_DEC, BL_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ KC_GRV, _______, _______, _______, _______, _______, _______, _______ ) diff --git a/keyboards/handwired/practice60/led.c b/keyboards/handwired/practice60/led.c index f15baed169..a9ede5bbaa 100644 --- a/keyboards/handwired/practice60/led.c +++ b/keyboards/handwired/practice60/led.c @@ -18,34 +18,240 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "hal.h" #include "backlight.h" #include "led.h" +#include "led_custom.h" #include "printf.h" +static void breathing_callback(PWMDriver *pwmp); + +static PWMConfig pwmCFG = { + 0xFFFF, /* PWM clock frequency */ + 256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ + NULL, /* No Callback */ + { + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */ + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL} + }, + 0, /* HW dependent part.*/ + 0 +}; + +static PWMConfig pwmCFG_breathing = { + 0xFFFF, /* 10kHz PWM clock frequency */ + 256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ + breathing_callback, /* Breathing Callback */ + { + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */ + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL} + }, + 0, /* HW dependent part.*/ + 0 +}; + +// 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 backlight_init_ports(void) { printf("backlight_init_ports()\n"); #ifdef BACKLIGHT_ENABLE - palSetPadMode(GPIOA, 8, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOA, 8); + + palSetPadMode(GPIOA, 8, PAL_MODE_STM32_ALTERNATE_PUSHPULL); + pwmStart(&PWMD1, &pwmCFG); + pwmEnableChannel(&PWMD1, 0, PWM_FRACTION_TO_WIDTH(&PWMD1, 0xFFFF,cie_lightness(0xFFFF))); #endif } void backlight_set(uint8_t level) { printf("backlight_set(%d)\n", level); #ifdef BACKLIGHT_ENABLE + uint32_t duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t) level / BACKLIGHT_LEVELS)); + printf("duty: (%d)\n", duty); if (level == 0) { // Turn backlight off - palSetPad(GPIOA, 8); + pwmDisableChannel(&PWMD1, 0); } else { - // Turn backlight on - palClearPad(GPIOA, 8); + // Turn backlight on + if(!is_breathing()){ + pwmEnableChannel(&PWMD1, 0, PWM_FRACTION_TO_WIDTH(&PWMD1,0xFFFF,duty)); + } } #endif } + +uint8_t backlight_tick = 0; + +void backlight_task(void) { +} + +#define BREATHING_NO_HALT 0 +#define BREATHING_HALT_OFF 1 +#define BREATHING_HALT_ON 2 +#define BREATHING_STEPS 128 + +static uint8_t breathing_period = BREATHING_PERIOD; +static uint8_t breathing_halt = BREATHING_NO_HALT; +static uint16_t breathing_counter = 0; + +bool is_breathing(void) { + return PWMD1.config == &pwmCFG_breathing; +} + +#define breathing_min() do {breathing_counter = 0;} while (0) +#define breathing_max() do {breathing_counter = breathing_period * 256 / 2;} while (0) + + +void breathing_interrupt_enable(void){ + pwmStop(&PWMD1); + printf("starting with callback\n"); + pwmStart(&PWMD1, &pwmCFG_breathing); + chSysLockFromISR(); + pwmEnablePeriodicNotification(&PWMD1); + pwmEnableChannelI( + &PWMD1, + 0, + PWM_FRACTION_TO_WIDTH( + &PWMD1, + 0xFFFF, + 0xFFFF + ) + ); + chSysUnlockFromISR(); +} + +void breathing_interrupt_disable(void){ + pwmStop(&PWMD1); + printf("starting without callback\n"); + pwmStart(&PWMD1, &pwmCFG); +} + +void breathing_enable(void) +{ + printf("breathing_enable()\n"); + breathing_counter = 0; + breathing_halt = BREATHING_NO_HALT; + breathing_interrupt_enable(); +} + +void breathing_pulse(void) +{ + if (get_backlight_level() == 0) + breathing_min(); + else + breathing_max(); + breathing_halt = BREATHING_HALT_ON; + breathing_interrupt_enable(); +} + +void breathing_disable(void) +{ + printf("breathing_disable()\n"); + breathing_interrupt_disable(); + // Restore backlight level + backlight_set(get_backlight_level()); +} + +void breathing_self_disable(void) +{ + if (get_backlight_level() == 0) + breathing_halt = BREATHING_HALT_OFF; + else + breathing_halt = BREATHING_HALT_ON; +} + +void breathing_toggle(void) { + if (is_breathing()){ + printf("disable breathing\n"); + breathing_disable(); + } else { + printf("enable breathing\n"); + breathing_enable(); + } +} + +void breathing_period_set(uint8_t value) +{ + if (!value) + value = 1; + breathing_period = value; +} + +void breathing_period_default(void) { + breathing_period_set(BREATHING_PERIOD); +} + +void breathing_period_inc(void) +{ + breathing_period_set(breathing_period+1); +} + +void breathing_period_dec(void) +{ + breathing_period_set(breathing_period-1); +} + +/* To generate breathing curve in python: + * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] + */ +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}; + +// Use this before the cie_lightness function. +static inline uint16_t scale_backlight(uint16_t v) { + return v / BACKLIGHT_LEVELS * get_backlight_level(); +} + +static void breathing_callback(PWMDriver *pwmp) +{ + (void)pwmp; + uint16_t interval = (uint16_t) breathing_period * 256 / BREATHING_STEPS; + // resetting after one period to prevent ugly reset at overflow. + breathing_counter = (breathing_counter + 1) % (breathing_period * 256); + uint8_t index = breathing_counter / interval % BREATHING_STEPS; + + if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || + ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) + { + breathing_interrupt_disable(); + } + + uint32_t duty = cie_lightness(scale_backlight(breathing_table[index] * 256)); + + chSysLockFromISR(); + pwmEnableChannelI( + &PWMD1, + 0, + PWM_FRACTION_TO_WIDTH( + &PWMD1, + 0xFFFF, + duty + ) + ); + chSysUnlockFromISR(); +} + + void led_set(uint8_t usb_led) { if (usb_led & (1<<USB_LED_CAPS_LOCK)) { - palClearPad(GPIOC, 13); + palSetPad(GPIOC, 13); } else { - palSetPad(GPIOC, 13); + palClearPad(GPIOC, 13); } } diff --git a/keyboards/handwired/practice60/led_custom.h b/keyboards/handwired/practice60/led_custom.h new file mode 100644 index 0000000000..8451c06d6f --- /dev/null +++ b/keyboards/handwired/practice60/led_custom.h @@ -0,0 +1,6 @@ +#pragma once + +void backlight_task(void); +void breathing_interrupt_disable(void); +void breathing_interrupt_enable(void); +bool is_breathing(void); diff --git a/keyboards/handwired/practice60/mcuconf.h b/keyboards/handwired/practice60/mcuconf.h index 9945e7408d..fced27289e 100644 --- a/keyboards/handwired/practice60/mcuconf.h +++ b/keyboards/handwired/practice60/mcuconf.h @@ -132,7 +132,7 @@ * PWM driver system settings. */ #define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM1 TRUE #define STM32_PWM_USE_TIM2 FALSE #define STM32_PWM_USE_TIM3 FALSE #define STM32_PWM_USE_TIM4 FALSE diff --git a/keyboards/handwired/practice60/practice60.c b/keyboards/handwired/practice60/practice60.c index 5d0fffbd09..acc0f00e53 100644 --- a/keyboards/handwired/practice60/practice60.c +++ b/keyboards/handwired/practice60/practice60.c @@ -3,8 +3,7 @@ #include "ch.h" #include "hal.h" - -#include "underglow.h" +#include "led_custom.h" #include "print.h" #include "debug.h" #include "util.h" @@ -19,14 +18,18 @@ void matrix_init_kb(void){ /* MOSI pin*/ palSetPadMode(GPIOB, 15, PAL_MODE_STM32_ALTERNATE_PUSHPULL); - LED_ON(); - palSetPad(GPIOA, 8); wait_ms(500); - palClearPad(GPIOA, 8); LED_OFF(); +#ifdef RGBLIGHT_ENABLE leds_init(); +#endif +} - +void matrix_scan_kb(void) +{ + #ifdef RGBLIGHT_ENABLE + rgblight_task(); + #endif } diff --git a/keyboards/handwired/practice60/rules.mk b/keyboards/handwired/practice60/rules.mk index 915b07320c..e417c91ee8 100644 --- a/keyboards/handwired/practice60/rules.mk +++ b/keyboards/handwired/practice60/rules.mk @@ -1,7 +1,6 @@ # project specific files SRC = led.c \ - underglow.c \ - hsv2rgb.c + ws2812.c # GENERIC STM32F103C8T6 board - stm32duino bootloader OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000 @@ -50,6 +49,7 @@ COMMAND_ENABLE = yes # Commands for debug and configuration SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover BACKLIGHT_ENABLE = yes +RGBLIGHT_ENABLE = yes LAYOUTS = 60_ansi diff --git a/keyboards/handwired/practice60/underglow.h b/keyboards/handwired/practice60/underglow.h deleted file mode 100644 index ff11952791..0000000000 --- a/keyboards/handwired/practice60/underglow.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "hsv2rgb.h" - -void set_leds_color_hsv(hsv_color color); -void set_leds_color_rgb(rgb_color color); -void set_led_color_hsv(hsv_color color, int pos); -void set_led_color_rgb(rgb_color color, int pos); - -void leds_init(void); diff --git a/keyboards/handwired/practice60/underglow.c b/keyboards/handwired/practice60/ws2812.c index 1383af1898..7d0f909c0c 100644 --- a/keyboards/handwired/practice60/underglow.c +++ b/keyboards/handwired/practice60/ws2812.c @@ -1,8 +1,12 @@ -#include "ch.h" -#include "hal.h" +/* + * LEDDriver.c + * + * Created on: Aug 26, 2013 + * Author: Omri Iluz + */ -#include "hsv2rgb.h" -#include "underglow.h" +#include "ws2812.h" +#include "stdlib.h" #define BYTES_FOR_LED_BYTE 4 #define NB_COLORS 3 @@ -10,18 +14,17 @@ #define DATA_SIZE BYTES_FOR_LED*NB_LEDS #define RESET_SIZE 200 #define PREAMBLE_SIZE 4 - // Define the spi your LEDs are plugged to here -#define LEDS_SPI SPID2 +#define WS2812_SPI SPID2 // Define the number of LEDs you wish to control in your LED strip -#define NB_LEDS 8 +#define NB_LEDS RGBLED_NUM -#define LED_SPIRAL 1 + #define LED_SPIRAL 1 -static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE]; + static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE]; static uint8_t get_protocol_eq(uint8_t data, int pos); -/* + /* * This lib is meant to be used asynchronously, thus the colors contained in * the txbuf will be sent in loop, so that the colors are always the ones you * put in the table (the user thus have less to worry about) @@ -37,38 +40,18 @@ static THD_WORKING_AREA(LEDS_THREAD_WA, 128); static THD_FUNCTION(ledsThread, arg) { (void) arg; while(1){ - spiSend(&LEDS_SPI, PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE, txbuf); - } -} - -#if LED_SPIRAL -/* - * 'Led spiral' is a simple demo in which we put all the leds to the same - * color, where this color does all the hsv circle in loop. - * If you want to launch the thread that will chage the led colors to the - * appropriate value, simply set LED_SPIRAL to 1. - */ -static THD_WORKING_AREA(HSVTRANS_WA, 128); -static THD_FUNCTION(hsv_transThread, arg){ - (void) arg; - hsv_color color = {0, 255, 127}; - while(1){ - color.h += 1; - color.h %= 256; - set_leds_color_hsv(color); - chThdSleepMilliseconds(50); + spiSend(&WS2812_SPI, PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE, txbuf); } } -#endif -static const SPIConfig spicfg = { + static const SPIConfig spicfg = { NULL, - GPIOB, - 15, - SPI_CR1_BR_1|SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us + PORT_WS2812, + PIN_WS2812, + SPI_CR1_BR_1|SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) }; -/* + /* * Function used to initialize the driver. * * Starts by shutting off all the LEDs. @@ -77,21 +60,19 @@ static const SPIConfig spicfg = { * txbuff values) */ void leds_init(void){ + /* MOSI pin*/ + palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_STM32_ALTERNATE_PUSHPULL); for(int i = 0; i < RESET_SIZE; i++) txbuf[DATA_SIZE+i] = 0x00; for (int i=0; i<PREAMBLE_SIZE; i++) txbuf[i] = 0x00; - spiAcquireBus(&LEDS_SPI); /* Acquire ownership of the bus. */ - spiStart(&LEDS_SPI, &spicfg); /* Setup transfer parameters. */ - spiSelect(&LEDS_SPI); /* Slave Select assertion. */ + spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ + spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ + spiSelect(&WS2812_SPI); /* Slave Select assertion. */ chThdCreateStatic(LEDS_THREAD_WA, sizeof(LEDS_THREAD_WA),NORMALPRIO, ledsThread, NULL); -#if LED_SPIRAL - chThdCreateStatic(HSVTRANS_WA, sizeof(HSVTRANS_WA), - NORMALPRIO, hsv_transThread, NULL); -#endif } -/* + /* * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to * the ws2812b protocol, we use this helper function to translate bytes into * 0s and 1s for the LED (with the appropriate timing). @@ -109,20 +90,20 @@ static uint8_t get_protocol_eq(uint8_t data, int pos){ return eq; } -/* - * If you want to set a LED's color in the HSV color space, simply call this - * function with a hsv_color containing the desired color and the index of the - * led on the LED strip (starting from 0, the first one being the closest the - * first plugged to the board) - * - * Only set the color of the LEDs through the functions given by this API - * (unless you really know what you are doing) - */ -void set_led_color_hsv(hsv_color color, int pos){ - set_led_color_rgb(hsv2rgb(color), pos); + + void WS2812_init(void) { + leds_init(); } -/* + void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { + uint8_t i = 0; + while (i < number_of_leds) { + set_led_color_rgb(ledarray[i], i); + i++; + } +} + + /* * If you want to set a LED's color in the RGB color space, simply call this * function with a hsv_color containing the desired color and the index of the * led on the LED strip (starting from 0, the first one being the closest the @@ -131,7 +112,7 @@ void set_led_color_hsv(hsv_color color, int pos){ * Only set the color of the LEDs through the functions given by this API * (unless you really know what you are doing) */ -void set_led_color_rgb(rgb_color color, int pos){ +void set_led_color_rgb(LED_TYPE color, int pos){ for(int j = 0; j < 4; j++) txbuf[PREAMBLE_SIZE + BYTES_FOR_LED*pos + j] = get_protocol_eq(color.g, j); for(int j = 0; j < 4; j++) @@ -140,18 +121,12 @@ void set_led_color_rgb(rgb_color color, int pos){ txbuf[PREAMBLE_SIZE + BYTES_FOR_LED*pos + BYTES_FOR_LED_BYTE*2+j] = get_protocol_eq(color.b, j); } -/* - * Same as the two above, but sets all the LEDs in the LED strip (HSV) - */ -void set_leds_color_hsv(hsv_color color){ + void set_leds_color_rgb(LED_TYPE color){ for(int i = 0; i < NB_LEDS; i++) - set_led_color_hsv(color, i); + set_led_color_rgb(color, i); } -/* - * Same as the two above, but sets all the LEDs in the LED strip (RGB) - */ -void set_leds_color_rgb(rgb_color color){ - for(int i = 0; i < NB_LEDS; i++) - set_led_color_rgb(color, i); -}
\ No newline at end of file + + void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds) { + + } diff --git a/keyboards/handwired/practice60/ws2812.h b/keyboards/handwired/practice60/ws2812.h new file mode 100644 index 0000000000..3b61ddcfa9 --- /dev/null +++ b/keyboards/handwired/practice60/ws2812.h @@ -0,0 +1,20 @@ +#pragma once + +#include "hal.h" +#include "rgblight_types.h" + + +void set_leds_color_rgb(LED_TYPE color); +void set_led_color_rgb(LED_TYPE color, int pos); +void leds_init(void); + + + // This is what users will use to interface with this +void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); +void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); + + +void WS2812_init(void); +void WS2812_set_color( uint8_t index, uint8_t red, uint8_t green, uint8_t blue ); +void WS2812_set_color_all( uint8_t red, uint8_t green, uint8_t blue ); +void WS2812_send_colors(void); diff --git a/quantum/rgblight.c b/quantum/rgblight.c index cf2666eb4b..22dce963c9 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -19,6 +19,11 @@ #include <avr/eeprom.h> #include <avr/interrupt.h> #endif +#ifdef STM32_EEPROM_ENABLE + #include "hal.h" + #include "eeprom.h" + #include "eeprom_stm32.h" +#endif #include "wait.h" #include "progmem.h" #include "timer.h" @@ -120,14 +125,14 @@ void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) { uint32_t eeconfig_read_rgblight(void) { - #ifdef __AVR__ + #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) return eeprom_read_dword(EECONFIG_RGBLIGHT); #else return 0; #endif } void eeconfig_update_rgblight(uint32_t val) { - #ifdef __AVR__ + #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) if (eeconfig_read_rgblight() != val) { eeprom_update_dword(EECONFIG_RGBLIGHT, val); } @@ -333,7 +338,7 @@ void rgblight_disable_noeeprom(void) { #ifdef RGBLIGHT_USE_TIMER rgblight_timer_disable(); #endif - _delay_ms(50); + wait_ms(50); rgblight_set(); } diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index a15430d676..17d38af6a0 100755 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -75,17 +75,13 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) { } // calculate which page is affected (Pagenum1/Pagenum2...PagenumN) - page = (FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)) & 0x00000FFF; - - if (page % FEE_PAGE_SIZE) page = page + FEE_PAGE_SIZE; - page = (page / FEE_PAGE_SIZE) - 1; + page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE; // if current data is 0xFF, the byte is empty, just overwrite with the new one if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) { FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte)); - } - else { + } else { // Copy Page to a buffer memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page @@ -96,18 +92,17 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) { } // manipulate desired data byte in temp data array if new byte is differ to the current - DataBuf[FEE_ADDR_OFFSET(Address)] = DataByte; + DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte; //Erase Page - FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + page); + FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)); - // Write new data (whole page) to flash if data has beed changed + // Write new data (whole page) to flash if data has been changed for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) { if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) { FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)])); } } - } return FlashStatus; } @@ -168,7 +163,7 @@ void eeprom_update_word (uint16_t *Address, uint16_t Value) uint32_t eeprom_read_dword (const uint32_t *Address) { const uint16_t p = (const uint32_t) Address; - return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8) + return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8) | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24); } |