diff options
Diffstat (limited to 'keyboards/ergodox/infinity')
| -rw-r--r-- | keyboards/ergodox/infinity/Makefile | 2 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/animations.c | 107 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/animations.h | 30 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/config.h | 4 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c | 37 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h | 80 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c | 411 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h | 11 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h | 2 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/gfxconf.h | 2 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/infinity.c | 51 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/infinity.h | 71 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/matrix.c | 1 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/rules.mk | 13 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/simple_visualizer.h | 123 | ||||
| -rw-r--r-- | keyboards/ergodox/infinity/visualizer.c | 329 |
16 files changed, 955 insertions, 319 deletions
diff --git a/keyboards/ergodox/infinity/Makefile b/keyboards/ergodox/infinity/Makefile index 191c6bb66..bd09e5885 100644 --- a/keyboards/ergodox/infinity/Makefile +++ b/keyboards/ergodox/infinity/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | ifndef MAKEFILE_INCLUDED | 1 | ifndef MAKEFILE_INCLUDED |
| 2 | include ../../../Makefile | 2 | include ../../../Makefile |
| 3 | endif \ No newline at end of file | 3 | endif |
diff --git a/keyboards/ergodox/infinity/animations.c b/keyboards/ergodox/infinity/animations.c new file mode 100644 index 000000000..4c9f6d9c8 --- /dev/null +++ b/keyboards/ergodox/infinity/animations.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #if defined(VISUALIZER_ENABLE) | ||
| 18 | |||
| 19 | #include "animations.h" | ||
| 20 | #include "visualizer.h" | ||
| 21 | #ifdef LCD_ENABLE | ||
| 22 | #include "lcd_keyframes.h" | ||
| 23 | #endif | ||
| 24 | #ifdef LCD_BACKLIGHT_ENABLE | ||
| 25 | #include "lcd_backlight_keyframes.h" | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #ifdef LED_ENABLE | ||
| 29 | #include "led_keyframes.h" | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #include "visualizer_keyframes.h" | ||
| 33 | |||
| 34 | |||
| 35 | #if defined(LCD_ENABLE) && defined(LCD_BACKLIGHT_ENABLE) | ||
| 36 | |||
| 37 | // Don't worry, if the startup animation is long, you can use the keyboard like normal | ||
| 38 | // during that time | ||
| 39 | keyframe_animation_t default_startup_animation = { | ||
| 40 | .num_frames = 4, | ||
| 41 | .loop = false, | ||
| 42 | .frame_lengths = {0, 0, 0, gfxMillisecondsToTicks(5000), 0}, | ||
| 43 | .frame_functions = { | ||
| 44 | lcd_keyframe_enable, | ||
| 45 | backlight_keyframe_enable, | ||
| 46 | lcd_keyframe_draw_logo, | ||
| 47 | backlight_keyframe_animate_color, | ||
| 48 | }, | ||
| 49 | }; | ||
| 50 | |||
| 51 | keyframe_animation_t default_suspend_animation = { | ||
| 52 | .num_frames = 4, | ||
| 53 | .loop = false, | ||
| 54 | .frame_lengths = {0, gfxMillisecondsToTicks(1000), 0, 0}, | ||
| 55 | .frame_functions = { | ||
| 56 | lcd_keyframe_display_layer_text, | ||
| 57 | backlight_keyframe_animate_color, | ||
| 58 | lcd_keyframe_disable, | ||
| 59 | backlight_keyframe_disable, | ||
| 60 | }, | ||
| 61 | }; | ||
| 62 | #endif | ||
| 63 | |||
| 64 | #if defined(LED_ENABLE) | ||
| 65 | #define CROSSFADE_TIME 1000 | ||
| 66 | #define GRADIENT_TIME 3000 | ||
| 67 | |||
| 68 | keyframe_animation_t led_test_animation = { | ||
| 69 | .num_frames = 14, | ||
| 70 | .loop = true, | ||
| 71 | .frame_lengths = { | ||
| 72 | gfxMillisecondsToTicks(1000), // fade in | ||
| 73 | gfxMillisecondsToTicks(1000), // no op (leds on) | ||
| 74 | gfxMillisecondsToTicks(1000), // fade out | ||
| 75 | gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade | ||
| 76 | gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in) | ||
| 77 | gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade | ||
| 78 | gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom | ||
| 79 | 0, // mirror leds | ||
| 80 | gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade | ||
| 81 | gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out) | ||
| 82 | gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade | ||
| 83 | gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom | ||
| 84 | 0, // normal leds | ||
| 85 | gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade | ||
| 86 | |||
| 87 | }, | ||
| 88 | .frame_functions = { | ||
| 89 | led_keyframe_fade_in_all, | ||
| 90 | keyframe_no_operation, | ||
| 91 | led_keyframe_fade_out_all, | ||
| 92 | led_keyframe_crossfade, | ||
| 93 | led_keyframe_left_to_right_gradient, | ||
| 94 | led_keyframe_crossfade, | ||
| 95 | led_keyframe_top_to_bottom_gradient, | ||
| 96 | led_keyframe_mirror_orientation, | ||
| 97 | led_keyframe_crossfade, | ||
| 98 | led_keyframe_left_to_right_gradient, | ||
| 99 | led_keyframe_crossfade, | ||
| 100 | led_keyframe_top_to_bottom_gradient, | ||
| 101 | led_keyframe_normal_orientation, | ||
| 102 | led_keyframe_crossfade, | ||
| 103 | }, | ||
| 104 | }; | ||
| 105 | #endif | ||
| 106 | |||
| 107 | #endif | ||
diff --git a/keyboards/ergodox/infinity/animations.h b/keyboards/ergodox/infinity/animations.h new file mode 100644 index 000000000..6d8b9830d --- /dev/null +++ b/keyboards/ergodox/infinity/animations.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef KEYBOARDS_ERGODOX_INFINITY_ANIMATIONS_H_ | ||
| 18 | #define KEYBOARDS_ERGODOX_INFINITY_ANIMATIONS_H_ | ||
| 19 | |||
| 20 | #include "visualizer.h" | ||
| 21 | |||
| 22 | // You can use these default animations, but of course you can also write your own custom ones instead | ||
| 23 | extern keyframe_animation_t default_startup_animation; | ||
| 24 | extern keyframe_animation_t default_suspend_animation; | ||
| 25 | |||
| 26 | // An animation for testing and demonstrating the led support, should probably not be used for real world | ||
| 27 | // cases | ||
| 28 | extern keyframe_animation_t led_test_animation; | ||
| 29 | |||
| 30 | #endif /* KEYBOARDS_ERGODOX_INFINITY_ANIMATIONS_H_ */ | ||
diff --git a/keyboards/ergodox/infinity/config.h b/keyboards/ergodox/infinity/config.h index 9e264083b..95f713819 100644 --- a/keyboards/ergodox/infinity/config.h +++ b/keyboards/ergodox/infinity/config.h | |||
| @@ -40,7 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 40 | /* number of backlight levels */ | 40 | /* number of backlight levels */ |
| 41 | #define BACKLIGHT_LEVELS 3 | 41 | #define BACKLIGHT_LEVELS 3 |
| 42 | 42 | ||
| 43 | #define LED_BRIGHTNESS_LO 15 | 43 | #define LED_BRIGHTNESS_LO 100 |
| 44 | #define LED_BRIGHTNESS_HI 255 | 44 | #define LED_BRIGHTNESS_HI 255 |
| 45 | 45 | ||
| 46 | /* define if matrix has ghost */ | 46 | /* define if matrix has ghost */ |
| @@ -54,6 +54,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 54 | // The visualizer needs gfx thread priorities | 54 | // The visualizer needs gfx thread priorities |
| 55 | #define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) | 55 | #define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) |
| 56 | 56 | ||
| 57 | #define VISUALIZER_USER_DATA_SIZE 16 | ||
| 58 | |||
| 57 | /* | 59 | /* |
| 58 | * Feature disable options | 60 | * Feature disable options |
| 59 | * These options are also useful to firmware size reduction. | 61 | * These options are also useful to firmware size reduction. |
diff --git a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c index 1d21f0c49..ea09c4bb0 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c +++ b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c | |||
| @@ -25,6 +25,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 25 | 25 | ||
| 26 | #include "board_IS31FL3731C.h" | 26 | #include "board_IS31FL3731C.h" |
| 27 | 27 | ||
| 28 | |||
| 29 | // Can't include led_tables from here | ||
| 30 | extern const uint8_t CIE1931_CURVE[]; | ||
| 31 | |||
| 28 | /*===========================================================================*/ | 32 | /*===========================================================================*/ |
| 29 | /* Driver local definitions. */ | 33 | /* Driver local definitions. */ |
| 30 | /*===========================================================================*/ | 34 | /*===========================================================================*/ |
| @@ -100,37 +104,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 100 | 104 | ||
| 101 | #define IS31 | 105 | #define IS31 |
| 102 | 106 | ||
| 103 | //Generated by http://jared.geek.nz/2013/feb/linear-led-pwm | ||
| 104 | const unsigned char cie[256] = { | ||
| 105 | 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, | ||
| 106 | 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, | ||
| 107 | 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, | ||
| 108 | 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, | ||
| 109 | 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, | ||
| 110 | 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, | ||
| 111 | 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, | ||
| 112 | 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, | ||
| 113 | 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, | ||
| 114 | 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, | ||
| 115 | 28, 28, 29, 29, 30, 31, 31, 32, 32, 33, | ||
| 116 | 34, 34, 35, 36, 37, 37, 38, 39, 39, 40, | ||
| 117 | 41, 42, 43, 43, 44, 45, 46, 47, 47, 48, | ||
| 118 | 49, 50, 51, 52, 53, 54, 54, 55, 56, 57, | ||
| 119 | 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, | ||
| 120 | 68, 70, 71, 72, 73, 74, 75, 76, 77, 79, | ||
| 121 | 80, 81, 82, 83, 85, 86, 87, 88, 90, 91, | ||
| 122 | 92, 94, 95, 96, 98, 99, 100, 102, 103, 105, | ||
| 123 | 106, 108, 109, 110, 112, 113, 115, 116, 118, 120, | ||
| 124 | 121, 123, 124, 126, 128, 129, 131, 132, 134, 136, | ||
| 125 | 138, 139, 141, 143, 145, 146, 148, 150, 152, 154, | ||
| 126 | 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, | ||
| 127 | 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, | ||
| 128 | 196, 198, 200, 202, 204, 207, 209, 211, 214, 216, | ||
| 129 | 218, 220, 223, 225, 228, 230, 232, 235, 237, 240, | ||
| 130 | 242, 245, 247, 250, 252, 255, | ||
| 131 | }; | ||
| 132 | |||
| 133 | |||
| 134 | /*===========================================================================*/ | 107 | /*===========================================================================*/ |
| 135 | /* Driver local functions. */ | 108 | /* Driver local functions. */ |
| 136 | /*===========================================================================*/ | 109 | /*===========================================================================*/ |
| @@ -231,7 +204,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { | |||
| 231 | uint8_t* src = PRIV(g)->frame_buffer; | 204 | uint8_t* src = PRIV(g)->frame_buffer; |
| 232 | for (int y=0;y<GDISP_SCREEN_HEIGHT;y++) { | 205 | for (int y=0;y<GDISP_SCREEN_HEIGHT;y++) { |
| 233 | for (int x=0;x<GDISP_SCREEN_WIDTH;x++) { | 206 | for (int x=0;x<GDISP_SCREEN_WIDTH;x++) { |
| 234 | PRIV(g)->write_buffer[get_led_address(g, x, y)]=cie[*src]; | 207 | PRIV(g)->write_buffer[get_led_address(g, x, y)]=CIE1931_CURVE[*src]; |
| 235 | ++src; | 208 | ++src; |
| 236 | } | 209 | } |
| 237 | } | 210 | } |
diff --git a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h index 290571ce5..9650ffb44 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h +++ b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h | |||
| @@ -8,8 +8,6 @@ | |||
| 8 | #ifndef _GDISP_LLD_BOARD_H | 8 | #ifndef _GDISP_LLD_BOARD_H |
| 9 | #define _GDISP_LLD_BOARD_H | 9 | #define _GDISP_LLD_BOARD_H |
| 10 | 10 | ||
| 11 | #include "print.h" | ||
| 12 | |||
| 13 | #define ST7565_LCD_BIAS ST7565_LCD_BIAS_9 // actually 6 | 11 | #define ST7565_LCD_BIAS ST7565_LCD_BIAS_9 // actually 6 |
| 14 | #define ST7565_ADC ST7565_ADC_NORMAL | 12 | #define ST7565_ADC ST7565_ADC_NORMAL |
| 15 | #define ST7565_COM_SCAN ST7565_COM_SCAN_DEC | 13 | #define ST7565_COM_SCAN ST7565_COM_SCAN_DEC |
| @@ -39,35 +37,49 @@ | |||
| 39 | // MSB First | 37 | // MSB First |
| 40 | // CLK Low by default | 38 | // CLK Low by default |
| 41 | static const SPIConfig spi1config = { | 39 | static const SPIConfig spi1config = { |
| 42 | NULL, | 40 | // Operation complete callback or @p NULL. |
| 43 | /* HW dependent part.*/ | 41 | .end_cb = NULL, |
| 44 | ST7565_GPIOPORT, | 42 | //The chip select line port - when not using pcs. |
| 45 | ST7565_SS_PIN, | 43 | .ssport = ST7565_GPIOPORT, |
| 46 | SPIx_CTARn_FMSZ(7) | 44 | // brief The chip select line pad number - when not using pcs. |
| 47 | | SPIx_CTARn_ASC(7) | 45 | .sspad=ST7565_SS_PIN, |
| 48 | | SPIx_CTARn_DT(7) | 46 | // SPI initialization data. |
| 49 | | SPIx_CTARn_CSSCK(7) | 47 | .tar0 = |
| 50 | | SPIx_CTARn_PBR(0) | 48 | SPIx_CTARn_FMSZ(7) // Frame size = 8 bytes |
| 51 | | SPIx_CTARn_BR(7) | 49 | | SPIx_CTARn_ASC(1) // After SCK Delay Scaler (min 50 ns) = 55.56ns |
| 52 | //SPI_CR1_BR_0 | 50 | | SPIx_CTARn_DT(0) // Delay After Transfer Scaler (no minimum)= 27.78ns |
| 51 | | SPIx_CTARn_CSSCK(0) // PCS to SCK Delay Scaler (min 20 ns) = 27.78ns | ||
| 52 | | SPIx_CTARn_PBR(0) // Baud Rate Prescaler = 2 | ||
| 53 | | SPIx_CTARn_BR(0) // Baud rate (min 50ns) = 55.56ns | ||
| 53 | }; | 54 | }; |
| 54 | 55 | ||
| 55 | static bool_t st7565_is_data_mode = 1; | 56 | static GFXINLINE void acquire_bus(GDisplay *g) { |
| 57 | (void) g; | ||
| 58 | // Only the LCD is using the SPI bus, so no need to acquire | ||
| 59 | // spiAcquireBus(&SPID1); | ||
| 60 | spiSelect(&SPID1); | ||
| 61 | } | ||
| 62 | |||
| 63 | static GFXINLINE void release_bus(GDisplay *g) { | ||
| 64 | (void) g; | ||
| 65 | // Only the LCD is using the SPI bus, so no need to release | ||
| 66 | //spiReleaseBus(&SPID1); | ||
| 67 | spiUnselect(&SPID1); | ||
| 68 | } | ||
| 56 | 69 | ||
| 57 | static GFXINLINE void init_board(GDisplay *g) { | 70 | static GFXINLINE void init_board(GDisplay *g) { |
| 58 | (void) g; | 71 | (void) g; |
| 59 | palSetPadModeNamed(A0, PAL_MODE_OUTPUT_PUSHPULL); | 72 | palSetPadModeNamed(A0, PAL_MODE_OUTPUT_PUSHPULL); |
| 60 | palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); | 73 | palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); |
| 61 | st7565_is_data_mode = 1; | ||
| 62 | palSetPadModeNamed(RST, PAL_MODE_OUTPUT_PUSHPULL); | 74 | palSetPadModeNamed(RST, PAL_MODE_OUTPUT_PUSHPULL); |
| 63 | palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN); | 75 | palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN); |
| 64 | palSetPadModeRaw(MOSI, ST7565_SPI_MODE); | 76 | palSetPadModeRaw(MOSI, ST7565_SPI_MODE); |
| 65 | palSetPadModeRaw(SLCK, ST7565_SPI_MODE); | 77 | palSetPadModeRaw(SLCK, ST7565_SPI_MODE); |
| 66 | palSetPadModeRaw(SS, ST7565_SPI_MODE); | 78 | palSetPadModeNamed(SS, PAL_MODE_OUTPUT_PUSHPULL); |
| 67 | 79 | ||
| 68 | spiInit(); | 80 | spiInit(); |
| 69 | spiStart(&SPID1, &spi1config); | 81 | spiStart(&SPID1, &spi1config); |
| 70 | spiSelect(&SPID1); | 82 | release_bus(g); |
| 71 | } | 83 | } |
| 72 | 84 | ||
| 73 | static GFXINLINE void post_init_board(GDisplay *g) { | 85 | static GFXINLINE void post_init_board(GDisplay *g) { |
| @@ -84,43 +96,17 @@ static GFXINLINE void setpin_reset(GDisplay *g, bool_t state) { | |||
| 84 | } | 96 | } |
| 85 | } | 97 | } |
| 86 | 98 | ||
| 87 | static GFXINLINE void acquire_bus(GDisplay *g) { | 99 | static GFXINLINE void enter_data_mode(GDisplay *g) { |
| 88 | (void) g; | 100 | palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); |
| 89 | // Only the LCD is using the SPI bus, so no need to acquire | ||
| 90 | // spiAcquireBus(&SPID1); | ||
| 91 | } | 101 | } |
| 92 | 102 | ||
| 93 | static GFXINLINE void release_bus(GDisplay *g) { | 103 | static GFXINLINE void enter_cmd_mode(GDisplay *g) { |
| 94 | (void) g; | 104 | palClearPad(ST7565_GPIOPORT, ST7565_A0_PIN); |
| 95 | // Only the LCD is using the SPI bus, so no need to release | ||
| 96 | //spiReleaseBus(&SPID1); | ||
| 97 | } | 105 | } |
| 98 | 106 | ||
| 99 | static GFXINLINE void write_cmd(GDisplay *g, uint8_t cmd) { | ||
| 100 | (void) g; | ||
| 101 | if (st7565_is_data_mode) { | ||
| 102 | // The sleeps need to be at lest 10 vs 25 ns respectively | ||
| 103 | // So let's sleep two ticks, one tick might not be enough | ||
| 104 | // if we are at the end of the tick | ||
| 105 | chThdSleep(2); | ||
| 106 | palClearPad(ST7565_GPIOPORT, ST7565_A0_PIN); | ||
| 107 | chThdSleep(2); | ||
| 108 | st7565_is_data_mode = 0; | ||
| 109 | } | ||
| 110 | spiSend(&SPID1, 1, &cmd); | ||
| 111 | } | ||
| 112 | 107 | ||
| 113 | static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) { | 108 | static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) { |
| 114 | (void) g; | 109 | (void) g; |
| 115 | if (!st7565_is_data_mode) { | ||
| 116 | // The sleeps need to be at lest 10 vs 25 ns respectively | ||
| 117 | // So let's sleep two ticks, one tick might not be enough | ||
| 118 | // if we are at the end of the tick | ||
| 119 | chThdSleep(2); | ||
| 120 | palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); | ||
| 121 | chThdSleep(2); | ||
| 122 | st7565_is_data_mode = 1; | ||
| 123 | } | ||
| 124 | spiSend(&SPID1, length, data); | 110 | spiSend(&SPID1, length, data); |
| 125 | } | 111 | } |
| 126 | 112 | ||
diff --git a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c index c33aea81a..b04ad0293 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c +++ b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c | |||
| @@ -20,16 +20,16 @@ | |||
| 20 | /*===========================================================================*/ | 20 | /*===========================================================================*/ |
| 21 | 21 | ||
| 22 | #ifndef GDISP_SCREEN_HEIGHT | 22 | #ifndef GDISP_SCREEN_HEIGHT |
| 23 | #define GDISP_SCREEN_HEIGHT 32 | 23 | #define GDISP_SCREEN_HEIGHT 32 |
| 24 | #endif | 24 | #endif |
| 25 | #ifndef GDISP_SCREEN_WIDTH | 25 | #ifndef GDISP_SCREEN_WIDTH |
| 26 | #define GDISP_SCREEN_WIDTH 128 | 26 | #define GDISP_SCREEN_WIDTH 128 |
| 27 | #endif | 27 | #endif |
| 28 | #ifndef GDISP_INITIAL_CONTRAST | 28 | #ifndef GDISP_INITIAL_CONTRAST |
| 29 | #define GDISP_INITIAL_CONTRAST 0 | 29 | #define GDISP_INITIAL_CONTRAST 35 |
| 30 | #endif | 30 | #endif |
| 31 | #ifndef GDISP_INITIAL_BACKLIGHT | 31 | #ifndef GDISP_INITIAL_BACKLIGHT |
| 32 | #define GDISP_INITIAL_BACKLIGHT 100 | 32 | #define GDISP_INITIAL_BACKLIGHT 100 |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | #define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0) | 35 | #define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0) |
| @@ -40,16 +40,16 @@ | |||
| 40 | /* Driver config defaults for backward compatibility. */ | 40 | /* Driver config defaults for backward compatibility. */ |
| 41 | /*===========================================================================*/ | 41 | /*===========================================================================*/ |
| 42 | #ifndef ST7565_LCD_BIAS | 42 | #ifndef ST7565_LCD_BIAS |
| 43 | #define ST7565_LCD_BIAS ST7565_LCD_BIAS_7 | 43 | #define ST7565_LCD_BIAS ST7565_LCD_BIAS_7 |
| 44 | #endif | 44 | #endif |
| 45 | #ifndef ST7565_ADC | 45 | #ifndef ST7565_ADC |
| 46 | #define ST7565_ADC ST7565_ADC_NORMAL | 46 | #define ST7565_ADC ST7565_ADC_NORMAL |
| 47 | #endif | 47 | #endif |
| 48 | #ifndef ST7565_COM_SCAN | 48 | #ifndef ST7565_COM_SCAN |
| 49 | #define ST7565_COM_SCAN ST7565_COM_SCAN_INC | 49 | #define ST7565_COM_SCAN ST7565_COM_SCAN_INC |
| 50 | #endif | 50 | #endif |
| 51 | #ifndef ST7565_PAGE_ORDER | 51 | #ifndef ST7565_PAGE_ORDER |
| 52 | #define ST7565_PAGE_ORDER 0,1,2,3 | 52 | #define ST7565_PAGE_ORDER 0,1,2,3 |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | /*===========================================================================*/ | 55 | /*===========================================================================*/ |
| @@ -58,12 +58,24 @@ | |||
| 58 | 58 | ||
| 59 | typedef struct{ | 59 | typedef struct{ |
| 60 | bool_t buffer2; | 60 | bool_t buffer2; |
| 61 | uint8_t data_pos; | ||
| 62 | uint8_t data[16]; | ||
| 61 | uint8_t ram[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8]; | 63 | uint8_t ram[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8]; |
| 62 | }PrivData; | 64 | }PrivData; |
| 63 | 65 | ||
| 64 | // Some common routines and macros | 66 | // Some common routines and macros |
| 65 | #define PRIV(g) ((PrivData*)g->priv) | 67 | #define PRIV(g) ((PrivData*)g->priv) |
| 66 | #define RAM(g) (PRIV(g)->ram) | 68 | #define RAM(g) (PRIV(g)->ram) |
| 69 | |||
| 70 | static GFXINLINE void write_cmd(GDisplay* g, uint8_t cmd) { | ||
| 71 | PRIV(g)->data[PRIV(g)->data_pos++] = cmd; | ||
| 72 | } | ||
| 73 | |||
| 74 | static GFXINLINE void flush_cmd(GDisplay* g) { | ||
| 75 | write_data(g, PRIV(g)->data, PRIV(g)->data_pos); | ||
| 76 | PRIV(g)->data_pos = 0; | ||
| 77 | } | ||
| 78 | |||
| 67 | #define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); } | 79 | #define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); } |
| 68 | #define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); } | 80 | #define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); } |
| 69 | 81 | ||
| @@ -86,207 +98,232 @@ typedef struct{ | |||
| 86 | */ | 98 | */ |
| 87 | 99 | ||
| 88 | LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { | 100 | LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { |
| 89 | // The private area is the display surface. | 101 | // The private area is the display surface. |
| 90 | g->priv = gfxAlloc(sizeof(PrivData)); | 102 | g->priv = gfxAlloc(sizeof(PrivData)); |
| 91 | PRIV(g)->buffer2 = false; | 103 | PRIV(g)->buffer2 = false; |
| 92 | 104 | PRIV(g)->data_pos = 0; | |
| 93 | // Initialise the board interface | 105 | |
| 94 | init_board(g); | 106 | // Initialise the board interface |
| 95 | 107 | init_board(g); | |
| 96 | // Hardware reset | 108 | |
| 97 | setpin_reset(g, TRUE); | 109 | // Hardware reset |
| 98 | gfxSleepMilliseconds(20); | 110 | setpin_reset(g, TRUE); |
| 99 | setpin_reset(g, FALSE); | 111 | gfxSleepMilliseconds(20); |
| 100 | gfxSleepMilliseconds(20); | 112 | setpin_reset(g, FALSE); |
| 101 | 113 | gfxSleepMilliseconds(20); | |
| 102 | acquire_bus(g); | 114 | acquire_bus(g); |
| 103 | write_cmd(g, ST7565_DISPLAY_OFF); | 115 | enter_cmd_mode(g); |
| 104 | write_cmd(g, ST7565_LCD_BIAS); | 116 | |
| 117 | write_cmd(g, ST7565_RESET); | ||
| 118 | write_cmd(g, ST7565_LCD_BIAS); | ||
| 105 | write_cmd(g, ST7565_ADC); | 119 | write_cmd(g, ST7565_ADC); |
| 106 | write_cmd(g, ST7565_COM_SCAN); | 120 | write_cmd(g, ST7565_COM_SCAN); |
| 107 | |||
| 108 | write_cmd(g, ST7565_START_LINE | 0); | ||
| 109 | |||
| 110 | write_cmd(g, ST7565_RESISTOR_RATIO | 0x6); | ||
| 111 | |||
| 112 | // turn on voltage converter (VC=1, VR=0, VF=0) | ||
| 113 | write_cmd(g, ST7565_POWER_CONTROL | 0x04); | ||
| 114 | delay_ms(50); | ||
| 115 | 121 | ||
| 116 | // turn on voltage regulator (VC=1, VR=1, VF=0) | 122 | write_cmd(g, ST7565_RESISTOR_RATIO | 0x1); |
| 117 | write_cmd(g, ST7565_POWER_CONTROL | 0x06); | 123 | write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST); |
| 118 | delay_ms(50); | ||
| 119 | 124 | ||
| 120 | // turn on voltage follower (VC=1, VR=1, VF=1) | 125 | // turn on internal power supply (VC=1, VR=1, VF=1) |
| 121 | write_cmd(g, ST7565_POWER_CONTROL | 0x07); | 126 | write_cmd(g, ST7565_POWER_CONTROL | 0x07); |
| 122 | delay_ms(50); | ||
| 123 | 127 | ||
| 124 | write_cmd(g, 0xE2); | 128 | write_cmd(g, ST7565_INVERT_DISPLAY); |
| 125 | write_cmd(g, ST7565_COM_SCAN); | 129 | write_cmd(g, ST7565_ALLON_NORMAL); |
| 126 | write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101); | ||
| 127 | //write_cmd2(g, ST7565_CONTRAST, 0); | ||
| 128 | write_cmd(g, ST7565_DISPLAY_ON); | ||
| 129 | write_cmd(g, ST7565_ALLON_NORMAL); | ||
| 130 | write_cmd(g, ST7565_INVERT_DISPLAY); | ||
| 131 | 130 | ||
| 132 | write_cmd(g, ST7565_RMW); | 131 | write_cmd(g, ST7565_START_LINE | 0); |
| 132 | write_cmd(g, ST7565_RMW); | ||
| 133 | flush_cmd(g); | ||
| 133 | 134 | ||
| 134 | // Finish Init | 135 | // Finish Init |
| 135 | post_init_board(g); | 136 | post_init_board(g); |
| 136 | 137 | ||
| 137 | // Release the bus | 138 | // Release the bus |
| 138 | release_bus(g); | 139 | release_bus(g); |
| 139 | 140 | ||
| 140 | /* Initialise the GDISP structure */ | 141 | /* Initialise the GDISP structure */ |
| 141 | g->g.Width = GDISP_SCREEN_WIDTH; | 142 | g->g.Width = GDISP_SCREEN_WIDTH; |
| 142 | g->g.Height = GDISP_SCREEN_HEIGHT; | 143 | g->g.Height = GDISP_SCREEN_HEIGHT; |
| 143 | g->g.Orientation = GDISP_ROTATE_0; | 144 | g->g.Orientation = GDISP_ROTATE_0; |
| 144 | g->g.Powermode = powerOn; | 145 | g->g.Powermode = powerOff; |
| 145 | g->g.Backlight = GDISP_INITIAL_BACKLIGHT; | 146 | g->g.Backlight = GDISP_INITIAL_BACKLIGHT; |
| 146 | g->g.Contrast = GDISP_INITIAL_CONTRAST; | 147 | g->g.Contrast = GDISP_INITIAL_CONTRAST; |
| 147 | return TRUE; | 148 | return TRUE; |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | #if GDISP_HARDWARE_FLUSH | 151 | #if GDISP_HARDWARE_FLUSH |
| 151 | LLDSPEC void gdisp_lld_flush(GDisplay *g) { | 152 | LLDSPEC void gdisp_lld_flush(GDisplay *g) { |
| 152 | unsigned p; | 153 | unsigned p; |
| 153 | 154 | ||
| 154 | // Don't flush if we don't need it. | 155 | // Don't flush if we don't need it. |
| 155 | if (!(g->flags & GDISP_FLG_NEEDFLUSH)) | 156 | if (!(g->flags & GDISP_FLG_NEEDFLUSH)) |
| 156 | return; | 157 | return; |
| 157 | 158 | ||
| 158 | acquire_bus(g); | 159 | acquire_bus(g); |
| 159 | unsigned dstOffset = (PRIV(g)->buffer2 ? 4 : 0); | 160 | enter_cmd_mode(g); |
| 160 | for (p = 0; p < 4; p++) { | 161 | unsigned dstOffset = (PRIV(g)->buffer2 ? 4 : 0); |
| 161 | write_cmd(g, ST7565_PAGE | (p + dstOffset)); | 162 | for (p = 0; p < 4; p++) { |
| 162 | write_cmd(g, ST7565_COLUMN_MSB | 0); | 163 | write_cmd(g, ST7565_PAGE | (p + dstOffset)); |
| 163 | write_cmd(g, ST7565_COLUMN_LSB | 0); | 164 | write_cmd(g, ST7565_COLUMN_MSB | 0); |
| 164 | write_cmd(g, ST7565_RMW); | 165 | write_cmd(g, ST7565_COLUMN_LSB | 0); |
| 165 | write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH); | 166 | write_cmd(g, ST7565_RMW); |
| 166 | } | 167 | flush_cmd(g); |
| 167 | unsigned line = (PRIV(g)->buffer2 ? 32 : 0); | 168 | enter_data_mode(g); |
| 168 | write_cmd(g, ST7565_START_LINE | line); | 169 | write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH); |
| 169 | PRIV(g)->buffer2 = !PRIV(g)->buffer2; | 170 | enter_cmd_mode(g); |
| 170 | release_bus(g); | 171 | } |
| 171 | 172 | unsigned line = (PRIV(g)->buffer2 ? 32 : 0); | |
| 172 | g->flags &= ~GDISP_FLG_NEEDFLUSH; | 173 | write_cmd(g, ST7565_START_LINE | line); |
| 173 | } | 174 | flush_cmd(g); |
| 175 | PRIV(g)->buffer2 = !PRIV(g)->buffer2; | ||
| 176 | release_bus(g); | ||
| 177 | |||
| 178 | g->flags &= ~GDISP_FLG_NEEDFLUSH; | ||
| 179 | } | ||
| 174 | #endif | 180 | #endif |
| 175 | 181 | ||
| 176 | #if GDISP_HARDWARE_DRAWPIXEL | 182 | #if GDISP_HARDWARE_DRAWPIXEL |
| 177 | LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { | 183 | LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { |
| 178 | coord_t x, y; | 184 | coord_t x, y; |
| 179 | 185 | ||
| 180 | switch(g->g.Orientation) { | 186 | switch(g->g.Orientation) { |
| 181 | default: | 187 | default: |
| 182 | case GDISP_ROTATE_0: | 188 | case GDISP_ROTATE_0: |
| 183 | x = g->p.x; | 189 | x = g->p.x; |
| 184 | y = g->p.y; | 190 | y = g->p.y; |
| 185 | break; | 191 | break; |
| 186 | case GDISP_ROTATE_90: | 192 | case GDISP_ROTATE_90: |
| 187 | x = g->p.y; | 193 | x = g->p.y; |
| 188 | y = GDISP_SCREEN_HEIGHT-1 - g->p.x; | 194 | y = GDISP_SCREEN_HEIGHT-1 - g->p.x; |
| 189 | break; | 195 | break; |
| 190 | case GDISP_ROTATE_180: | 196 | case GDISP_ROTATE_180: |
| 191 | x = GDISP_SCREEN_WIDTH-1 - g->p.x; | 197 | x = GDISP_SCREEN_WIDTH-1 - g->p.x; |
| 192 | y = GDISP_SCREEN_HEIGHT-1 - g->p.y; | 198 | y = GDISP_SCREEN_HEIGHT-1 - g->p.y; |
| 193 | break; | 199 | break; |
| 194 | case GDISP_ROTATE_270: | 200 | case GDISP_ROTATE_270: |
| 195 | x = GDISP_SCREEN_HEIGHT-1 - g->p.y; | 201 | x = GDISP_SCREEN_HEIGHT-1 - g->p.y; |
| 196 | y = g->p.x; | 202 | y = g->p.x; |
| 197 | break; | 203 | break; |
| 198 | } | 204 | } |
| 199 | if (gdispColor2Native(g->p.color) != Black) | 205 | if (gdispColor2Native(g->p.color) != Black) |
| 200 | RAM(g)[xyaddr(x, y)] |= xybit(y); | 206 | RAM(g)[xyaddr(x, y)] |= xybit(y); |
| 201 | else | 207 | else |
| 202 | RAM(g)[xyaddr(x, y)] &= ~xybit(y); | 208 | RAM(g)[xyaddr(x, y)] &= ~xybit(y); |
| 203 | g->flags |= GDISP_FLG_NEEDFLUSH; | 209 | g->flags |= GDISP_FLG_NEEDFLUSH; |
| 204 | } | 210 | } |
| 205 | #endif | 211 | #endif |
| 206 | 212 | ||
| 207 | #if GDISP_HARDWARE_PIXELREAD | 213 | #if GDISP_HARDWARE_PIXELREAD |
| 208 | LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { | 214 | LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { |
| 209 | coord_t x, y; | 215 | coord_t x, y; |
| 210 | 216 | ||
| 211 | switch(g->g.Orientation) { | 217 | switch(g->g.Orientation) { |
| 212 | default: | 218 | default: |
| 213 | case GDISP_ROTATE_0: | 219 | case GDISP_ROTATE_0: |
| 214 | x = g->p.x; | 220 | x = g->p.x; |
| 215 | y = g->p.y; | 221 | y = g->p.y; |
| 216 | break; | 222 | break; |
| 217 | case GDISP_ROTATE_90: | 223 | case GDISP_ROTATE_90: |
| 218 | x = g->p.y; | 224 | x = g->p.y; |
| 219 | y = GDISP_SCREEN_HEIGHT-1 - g->p.x; | 225 | y = GDISP_SCREEN_HEIGHT-1 - g->p.x; |
| 220 | break; | 226 | break; |
| 221 | case GDISP_ROTATE_180: | 227 | case GDISP_ROTATE_180: |
| 222 | x = GDISP_SCREEN_WIDTH-1 - g->p.x; | 228 | x = GDISP_SCREEN_WIDTH-1 - g->p.x; |
| 223 | y = GDISP_SCREEN_HEIGHT-1 - g->p.y; | 229 | y = GDISP_SCREEN_HEIGHT-1 - g->p.y; |
| 224 | break; | 230 | break; |
| 225 | case GDISP_ROTATE_270: | 231 | case GDISP_ROTATE_270: |
| 226 | x = GDISP_SCREEN_HEIGHT-1 - g->p.y; | 232 | x = GDISP_SCREEN_HEIGHT-1 - g->p.y; |
| 227 | y = g->p.x; | 233 | y = g->p.x; |
| 228 | break; | 234 | break; |
| 229 | } | 235 | } |
| 230 | return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black; | 236 | return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black; |
| 231 | } | 237 | } |
| 232 | #endif | 238 | #endif |
| 233 | 239 | ||
| 240 | LLDSPEC void gdisp_lld_blit_area(GDisplay *g) { | ||
| 241 | uint8_t* buffer = (uint8_t*)g->p.ptr; | ||
| 242 | int linelength = g->p.cx; | ||
| 243 | for (int i = 0; i < g->p.cy; i++) { | ||
| 244 | unsigned dstx = g->p.x; | ||
| 245 | unsigned dsty = g->p.y + i; | ||
| 246 | unsigned srcx = g->p.x1; | ||
| 247 | unsigned srcy = g->p.y1 + i; | ||
| 248 | unsigned srcbit = srcy * g->p.x2 + srcx; | ||
| 249 | for(int j=0; j < linelength; j++) { | ||
| 250 | uint8_t src = buffer[srcbit / 8]; | ||
| 251 | uint8_t bit = 7-(srcbit % 8); | ||
| 252 | uint8_t bitset = (src >> bit) & 1; | ||
| 253 | uint8_t* dst = &(RAM(g)[xyaddr(dstx, dsty)]); | ||
| 254 | if (bitset) { | ||
| 255 | *dst |= xybit(dsty); | ||
| 256 | } | ||
| 257 | else { | ||
| 258 | *dst &= ~xybit(dsty); | ||
| 259 | } | ||
| 260 | dstx++; | ||
| 261 | srcbit++; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | g->flags |= GDISP_FLG_NEEDFLUSH; | ||
| 265 | } | ||
| 266 | |||
| 234 | #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL | 267 | #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL |
| 235 | LLDSPEC void gdisp_lld_control(GDisplay *g) { | 268 | LLDSPEC void gdisp_lld_control(GDisplay *g) { |
| 236 | switch(g->p.x) { | 269 | switch(g->p.x) { |
| 237 | case GDISP_CONTROL_POWER: | 270 | case GDISP_CONTROL_POWER: |
| 238 | if (g->g.Powermode == (powermode_t)g->p.ptr) | 271 | if (g->g.Powermode == (powermode_t)g->p.ptr) |
| 239 | return; | 272 | return; |
| 240 | switch((powermode_t)g->p.ptr) { | 273 | switch((powermode_t)g->p.ptr) { |
| 241 | case powerOff: | 274 | case powerOff: |
| 242 | case powerSleep: | 275 | case powerSleep: |
| 243 | case powerDeepSleep: | 276 | case powerDeepSleep: |
| 244 | acquire_bus(g); | 277 | acquire_bus(g); |
| 245 | write_cmd(g, ST7565_DISPLAY_OFF); | 278 | enter_cmd_mode(g); |
| 246 | release_bus(g); | 279 | write_cmd(g, ST7565_DISPLAY_OFF); |
| 247 | break; | 280 | flush_cmd(g); |
| 248 | case powerOn: | 281 | release_bus(g); |
| 249 | acquire_bus(g); | 282 | break; |
| 250 | write_cmd(g, ST7565_DISPLAY_ON); | 283 | case powerOn: |
| 251 | release_bus(g); | 284 | acquire_bus(g); |
| 252 | break; | 285 | enter_cmd_mode(g); |
| 253 | default: | 286 | write_cmd(g, ST7565_DISPLAY_ON); |
| 254 | return; | 287 | flush_cmd(g); |
| 255 | } | 288 | release_bus(g); |
| 256 | g->g.Powermode = (powermode_t)g->p.ptr; | 289 | break; |
| 257 | return; | 290 | default: |
| 258 | 291 | return; | |
| 259 | case GDISP_CONTROL_ORIENTATION: | 292 | } |
| 260 | if (g->g.Orientation == (orientation_t)g->p.ptr) | 293 | g->g.Powermode = (powermode_t)g->p.ptr; |
| 261 | return; | 294 | return; |
| 262 | switch((orientation_t)g->p.ptr) { | 295 | |
| 263 | /* Rotation is handled by the drawing routines */ | 296 | case GDISP_CONTROL_ORIENTATION: |
| 264 | case GDISP_ROTATE_0: | 297 | if (g->g.Orientation == (orientation_t)g->p.ptr) |
| 265 | case GDISP_ROTATE_180: | 298 | return; |
| 266 | g->g.Height = GDISP_SCREEN_HEIGHT; | 299 | switch((orientation_t)g->p.ptr) { |
| 267 | g->g.Width = GDISP_SCREEN_WIDTH; | 300 | /* Rotation is handled by the drawing routines */ |
| 268 | break; | 301 | case GDISP_ROTATE_0: |
| 269 | case GDISP_ROTATE_90: | 302 | case GDISP_ROTATE_180: |
| 270 | case GDISP_ROTATE_270: | 303 | g->g.Height = GDISP_SCREEN_HEIGHT; |
| 271 | g->g.Height = GDISP_SCREEN_WIDTH; | 304 | g->g.Width = GDISP_SCREEN_WIDTH; |
| 272 | g->g.Width = GDISP_SCREEN_HEIGHT; | 305 | break; |
| 273 | break; | 306 | case GDISP_ROTATE_90: |
| 274 | default: | 307 | case GDISP_ROTATE_270: |
| 275 | return; | 308 | g->g.Height = GDISP_SCREEN_WIDTH; |
| 276 | } | 309 | g->g.Width = GDISP_SCREEN_HEIGHT; |
| 277 | g->g.Orientation = (orientation_t)g->p.ptr; | 310 | break; |
| 278 | return; | 311 | default: |
| 279 | 312 | return; | |
| 280 | case GDISP_CONTROL_CONTRAST: | 313 | } |
| 281 | if ((unsigned)g->p.ptr > 100) | 314 | g->g.Orientation = (orientation_t)g->p.ptr; |
| 282 | g->p.ptr = (void *)100; | 315 | return; |
| 283 | acquire_bus(g); | 316 | |
| 284 | write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F); | 317 | case GDISP_CONTROL_CONTRAST: |
| 285 | release_bus(g); | 318 | g->g.Contrast = (unsigned)g->p.ptr & 63; |
| 286 | g->g.Contrast = (unsigned)g->p.ptr; | 319 | acquire_bus(g); |
| 287 | return; | 320 | enter_cmd_mode(g); |
| 288 | } | 321 | write_cmd2(g, ST7565_CONTRAST, g->g.Contrast); |
| 289 | } | 322 | flush_cmd(g); |
| 323 | release_bus(g); | ||
| 324 | return; | ||
| 325 | } | ||
| 326 | } | ||
| 290 | #endif // GDISP_NEED_CONTROL | 327 | #endif // GDISP_NEED_CONTROL |
| 291 | 328 | ||
| 292 | #endif // GFX_USE_GDISP | 329 | #endif // GFX_USE_GDISP |
diff --git a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h index 48587b9e1..2b66a877c 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h +++ b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h | |||
| @@ -14,12 +14,13 @@ | |||
| 14 | /* Driver hardware support. */ | 14 | /* Driver hardware support. */ |
| 15 | /*===========================================================================*/ | 15 | /*===========================================================================*/ |
| 16 | 16 | ||
| 17 | #define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing | 17 | #define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing |
| 18 | #define GDISP_HARDWARE_DRAWPIXEL TRUE | 18 | #define GDISP_HARDWARE_DRAWPIXEL TRUE |
| 19 | #define GDISP_HARDWARE_PIXELREAD TRUE | 19 | #define GDISP_HARDWARE_PIXELREAD TRUE |
| 20 | #define GDISP_HARDWARE_CONTROL TRUE | 20 | #define GDISP_HARDWARE_CONTROL TRUE |
| 21 | #define GDISP_HARDWARE_BITFILLS TRUE | ||
| 21 | 22 | ||
| 22 | #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO | 23 | #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO |
| 23 | 24 | ||
| 24 | #endif /* GFX_USE_GDISP */ | 25 | #endif /* GFX_USE_GDISP */ |
| 25 | 26 | ||
diff --git a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h index 48636b33d..24924ff05 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h +++ b/keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h | |||
| @@ -34,4 +34,6 @@ | |||
| 34 | #define ST7565_RESISTOR_RATIO 0x20 | 34 | #define ST7565_RESISTOR_RATIO 0x20 |
| 35 | #define ST7565_POWER_CONTROL 0x28 | 35 | #define ST7565_POWER_CONTROL 0x28 |
| 36 | 36 | ||
| 37 | #define ST7565_RESET 0xE2 | ||
| 38 | |||
| 37 | #endif /* _ST7565_H */ | 39 | #endif /* _ST7565_H */ |
diff --git a/keyboards/ergodox/infinity/gfxconf.h b/keyboards/ergodox/infinity/gfxconf.h index 8caa577b7..45b9f5858 100644 --- a/keyboards/ergodox/infinity/gfxconf.h +++ b/keyboards/ergodox/infinity/gfxconf.h | |||
| @@ -143,7 +143,7 @@ | |||
| 143 | #define GDISP_HARDWARE_DRAWPIXEL TRUE | 143 | #define GDISP_HARDWARE_DRAWPIXEL TRUE |
| 144 | #define GDISP_HARDWARE_CLEARS FALSE | 144 | #define GDISP_HARDWARE_CLEARS FALSE |
| 145 | #define GDISP_HARDWARE_FILLS FALSE | 145 | #define GDISP_HARDWARE_FILLS FALSE |
| 146 | #define GDISP_HARDWARE_BITFILLS FALSE | 146 | //#define GDISP_HARDWARE_BITFILLS FALSE |
| 147 | #define GDISP_HARDWARE_SCROLL FALSE | 147 | #define GDISP_HARDWARE_SCROLL FALSE |
| 148 | #define GDISP_HARDWARE_PIXELREAD TRUE | 148 | #define GDISP_HARDWARE_PIXELREAD TRUE |
| 149 | #define GDISP_HARDWARE_CONTROL TRUE | 149 | #define GDISP_HARDWARE_CONTROL TRUE |
diff --git a/keyboards/ergodox/infinity/infinity.c b/keyboards/ergodox/infinity/infinity.c index 02db67eaf..62259ed3f 100644 --- a/keyboards/ergodox/infinity/infinity.c +++ b/keyboards/ergodox/infinity/infinity.c | |||
| @@ -70,10 +70,33 @@ void lcd_backlight_hal_init(void) { | |||
| 70 | RGB_PORT->PCR[BLUE_PIN] = RGB_MODE; | 70 | RGB_PORT->PCR[BLUE_PIN] = RGB_MODE; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static uint16_t cie_lightness(uint16_t v) { | ||
| 74 | // The CIE 1931 formula for lightness | ||
| 75 | // Y = luminance (output) 0-1 | ||
| 76 | // L = lightness input 0 - 100 | ||
| 77 | |||
| 78 | // Y = (L* / 902.3) if L* <= 8 | ||
| 79 | // Y = ((L* + 16) / 116)^3 if L* > 8 | ||
| 80 | |||
| 81 | float l = 100.0f * (v / 65535.0f); | ||
| 82 | float y = 0.0f; | ||
| 83 | if (l <= 8.0f) { | ||
| 84 | y = l / 902.3; | ||
| 85 | } | ||
| 86 | else { | ||
| 87 | y = ((l + 16.0f) / 116.0f); | ||
| 88 | y = y * y * y; | ||
| 89 | if (y > 1.0f) { | ||
| 90 | y = 1.0f; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | return y * 65535.0f; | ||
| 94 | } | ||
| 95 | |||
| 73 | void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { | 96 | void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { |
| 74 | CHANNEL_RED.CnV = r; | 97 | CHANNEL_RED.CnV = cie_lightness(r); |
| 75 | CHANNEL_GREEN.CnV = g; | 98 | CHANNEL_GREEN.CnV = cie_lightness(g); |
| 76 | CHANNEL_BLUE.CnV = b; | 99 | CHANNEL_BLUE.CnV = cie_lightness(b); |
| 77 | } | 100 | } |
| 78 | 101 | ||
| 79 | __attribute__ ((weak)) | 102 | __attribute__ ((weak)) |
| @@ -103,34 +126,48 @@ void matrix_scan_kb(void) { | |||
| 103 | matrix_scan_user(); | 126 | matrix_scan_user(); |
| 104 | } | 127 | } |
| 105 | 128 | ||
| 129 | __attribute__ ((weak)) | ||
| 106 | void ergodox_board_led_on(void){ | 130 | void ergodox_board_led_on(void){ |
| 107 | } | 131 | } |
| 108 | 132 | ||
| 133 | __attribute__ ((weak)) | ||
| 109 | void ergodox_right_led_1_on(void){ | 134 | void ergodox_right_led_1_on(void){ |
| 110 | } | 135 | } |
| 111 | 136 | ||
| 137 | __attribute__ ((weak)) | ||
| 112 | void ergodox_right_led_2_on(void){ | 138 | void ergodox_right_led_2_on(void){ |
| 113 | } | 139 | } |
| 114 | 140 | ||
| 141 | __attribute__ ((weak)) | ||
| 115 | void ergodox_right_led_3_on(void){ | 142 | void ergodox_right_led_3_on(void){ |
| 116 | } | 143 | } |
| 117 | 144 | ||
| 118 | void ergodox_right_led_on(uint8_t led){ | 145 | __attribute__ ((weak)) |
| 119 | } | ||
| 120 | |||
| 121 | void ergodox_board_led_off(void){ | 146 | void ergodox_board_led_off(void){ |
| 122 | } | 147 | } |
| 123 | 148 | ||
| 149 | __attribute__ ((weak)) | ||
| 124 | void ergodox_right_led_1_off(void){ | 150 | void ergodox_right_led_1_off(void){ |
| 125 | } | 151 | } |
| 126 | 152 | ||
| 153 | __attribute__ ((weak)) | ||
| 127 | void ergodox_right_led_2_off(void){ | 154 | void ergodox_right_led_2_off(void){ |
| 128 | } | 155 | } |
| 129 | 156 | ||
| 157 | __attribute__ ((weak)) | ||
| 130 | void ergodox_right_led_3_off(void){ | 158 | void ergodox_right_led_3_off(void){ |
| 131 | } | 159 | } |
| 132 | 160 | ||
| 133 | void ergodox_right_led_off(uint8_t led){ | 161 | __attribute__ ((weak)) |
| 162 | void ergodox_right_led_1_set(uint8_t n) { | ||
| 163 | } | ||
| 164 | |||
| 165 | __attribute__ ((weak)) | ||
| 166 | void ergodox_right_led_2_set(uint8_t n) { | ||
| 167 | } | ||
| 168 | |||
| 169 | __attribute__ ((weak)) | ||
| 170 | void ergodox_right_led_3_set(uint8_t n) { | ||
| 134 | } | 171 | } |
| 135 | 172 | ||
| 136 | #ifdef ONEHAND_ENABLE | 173 | #ifdef ONEHAND_ENABLE |
diff --git a/keyboards/ergodox/infinity/infinity.h b/keyboards/ergodox/infinity/infinity.h index fec9e565c..73a0f4bf7 100644 --- a/keyboards/ergodox/infinity/infinity.h +++ b/keyboards/ergodox/infinity/infinity.h | |||
| @@ -7,13 +7,38 @@ void ergodox_board_led_on(void); | |||
| 7 | void ergodox_right_led_1_on(void); | 7 | void ergodox_right_led_1_on(void); |
| 8 | void ergodox_right_led_2_on(void); | 8 | void ergodox_right_led_2_on(void); |
| 9 | void ergodox_right_led_3_on(void); | 9 | void ergodox_right_led_3_on(void); |
| 10 | void ergodox_right_led_on(uint8_t led); | 10 | |
| 11 | inline void ergodox_right_led_on(uint8_t led) { | ||
| 12 | switch (led) { | ||
| 13 | case 0: | ||
| 14 | ergodox_right_led_1_on(); | ||
| 15 | break; | ||
| 16 | case 1: | ||
| 17 | ergodox_right_led_2_on(); | ||
| 18 | break; | ||
| 19 | case 2: | ||
| 20 | ergodox_right_led_3_on(); | ||
| 21 | break; | ||
| 22 | } | ||
| 23 | } | ||
| 11 | 24 | ||
| 12 | void ergodox_board_led_off(void); | 25 | void ergodox_board_led_off(void); |
| 13 | void ergodox_right_led_1_off(void); | 26 | void ergodox_right_led_1_off(void); |
| 14 | void ergodox_right_led_2_off(void); | 27 | void ergodox_right_led_2_off(void); |
| 15 | void ergodox_right_led_3_off(void); | 28 | void ergodox_right_led_3_off(void); |
| 16 | void ergodox_right_led_off(uint8_t led); | 29 | inline void ergodox_right_led_off(uint8_t led) { |
| 30 | switch (led) { | ||
| 31 | case 0: | ||
| 32 | ergodox_right_led_1_off(); | ||
| 33 | break; | ||
| 34 | case 1: | ||
| 35 | ergodox_right_led_2_off(); | ||
| 36 | break; | ||
| 37 | case 2: | ||
| 38 | ergodox_right_led_3_off(); | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | } | ||
| 17 | 42 | ||
| 18 | inline void ergodox_led_all_on(void) | 43 | inline void ergodox_led_all_on(void) |
| 19 | { | 44 | { |
| @@ -31,36 +56,22 @@ inline void ergodox_led_all_off(void) | |||
| 31 | ergodox_right_led_3_off(); | 56 | ergodox_right_led_3_off(); |
| 32 | } | 57 | } |
| 33 | 58 | ||
| 34 | inline void ergodox_right_led_1_set(uint8_t n){ | 59 | void ergodox_right_led_1_set(uint8_t n); |
| 35 | if (n) { | 60 | void ergodox_right_led_2_set(uint8_t n); |
| 36 | ergodox_right_led_1_on(); | 61 | void ergodox_right_led_3_set(uint8_t n); |
| 37 | } else { | ||
| 38 | ergodox_right_led_1_off(); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | inline void ergodox_right_led_2_set(uint8_t n){ | ||
| 43 | if (n) { | ||
| 44 | ergodox_right_led_2_on(); | ||
| 45 | } else { | ||
| 46 | ergodox_right_led_2_off(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | inline void ergodox_right_led_3_set(uint8_t n){ | ||
| 51 | if (n) { | ||
| 52 | ergodox_right_led_3_on(); | ||
| 53 | } else { | ||
| 54 | ergodox_right_led_3_off(); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | 62 | ||
| 58 | inline void ergodox_right_led_set(uint8_t led, uint8_t n){ | 63 | inline void ergodox_right_led_set(uint8_t led, uint8_t n){ |
| 59 | if (n) { | 64 | switch (led) { |
| 60 | ergodox_right_led_on(led); | 65 | case 0: |
| 61 | } else { | 66 | ergodox_right_led_1_set(n); |
| 62 | ergodox_right_led_off(led); | 67 | break; |
| 63 | } | 68 | case 1: |
| 69 | ergodox_right_led_2_set(n); | ||
| 70 | break; | ||
| 71 | case 2: | ||
| 72 | ergodox_right_led_3_set(n); | ||
| 73 | break; | ||
| 74 | } | ||
| 64 | } | 75 | } |
| 65 | 76 | ||
| 66 | inline void ergodox_led_all_set(uint8_t n) { | 77 | inline void ergodox_led_all_set(uint8_t n) { |
diff --git a/keyboards/ergodox/infinity/matrix.c b/keyboards/ergodox/infinity/matrix.c index 1fda90484..3364f8c90 100644 --- a/keyboards/ergodox/infinity/matrix.c +++ b/keyboards/ergodox/infinity/matrix.c | |||
| @@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 24 | #include "print.h" | 24 | #include "print.h" |
| 25 | #include "debug.h" | 25 | #include "debug.h" |
| 26 | #include "matrix.h" | 26 | #include "matrix.h" |
| 27 | #include "serial_link/system/serial_link.h" | ||
| 27 | 28 | ||
| 28 | 29 | ||
| 29 | /* | 30 | /* |
diff --git a/keyboards/ergodox/infinity/rules.mk b/keyboards/ergodox/infinity/rules.mk index 473a6dfec..9e6170d89 100644 --- a/keyboards/ergodox/infinity/rules.mk +++ b/keyboards/ergodox/infinity/rules.mk | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | # project specific files | 1 | # project specific files |
| 2 | SRC = matrix.c \ | 2 | SRC = matrix.c \ |
| 3 | led.c | 3 | led.c \ |
| 4 | animations.c | ||
| 4 | 5 | ||
| 5 | ## chip/board settings | 6 | ## chip/board settings |
| 6 | # - the next two should match the directories in | 7 | # - the next two should match the directories in |
| @@ -59,21 +60,17 @@ OPT_DEFS += -DCORTEX_VTOR_INIT=0x00002000 | |||
| 59 | # | 60 | # |
| 60 | CUSTOM_MATRIX ?= yes # Custom matrix file | 61 | CUSTOM_MATRIX ?= yes # Custom matrix file |
| 61 | SERIAL_LINK_ENABLE = yes | 62 | SERIAL_LINK_ENABLE = yes |
| 62 | VISUALIZER_ENABLE ?= no #temporarily disabled to make everything compile | 63 | VISUALIZER_ENABLE ?= yes |
| 63 | LCD_ENABLE ?= yes | 64 | LCD_ENABLE ?= yes |
| 64 | LED_ENABLE ?= yes | 65 | LED_ENABLE ?= no |
| 65 | LCD_BACKLIGHT_ENABLE ?= yes | 66 | LCD_BACKLIGHT_ENABLE ?= yes |
| 66 | MIDI_ENABLE = no | 67 | MIDI_ENABLE = no |
| 67 | RGBLIGHT_ENABLE = no | 68 | RGBLIGHT_ENABLE = no |
| 68 | 69 | ||
| 69 | ifndef QUANTUM_DIR | ||
| 70 | include ../../../Makefile | ||
| 71 | endif | ||
| 72 | |||
| 73 | ifdef LCD_ENABLE | 70 | ifdef LCD_ENABLE |
| 74 | include $(SUBPROJECT_PATH)/drivers/gdisp/st7565ergodox/driver.mk | 71 | include $(SUBPROJECT_PATH)/drivers/gdisp/st7565ergodox/driver.mk |
| 75 | endif | 72 | endif |
| 76 | 73 | ||
| 77 | ifdef LED_ENABLE | 74 | ifdef LED_ENABLE |
| 78 | include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk | 75 | include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk |
| 79 | endif | 76 | endif \ No newline at end of file |
diff --git a/keyboards/ergodox/infinity/simple_visualizer.h b/keyboards/ergodox/infinity/simple_visualizer.h new file mode 100644 index 000000000..ded8a3222 --- /dev/null +++ b/keyboards/ergodox/infinity/simple_visualizer.h | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_ | ||
| 18 | #define KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_ | ||
| 19 | |||
| 20 | // Currently we are assuming that both the backlight and LCD are enabled | ||
| 21 | // But it's entirely possible to write a custom visualizer that use only | ||
| 22 | // one of them | ||
| 23 | #ifndef LCD_BACKLIGHT_ENABLE | ||
| 24 | #error This visualizer needs that LCD backlight is enabled | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #ifndef LCD_ENABLE | ||
| 28 | #error This visualizer needs that LCD is enabled | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #include "visualizer.h" | ||
| 32 | #include "visualizer_keyframes.h" | ||
| 33 | #include "lcd_keyframes.h" | ||
| 34 | #include "lcd_backlight_keyframes.h" | ||
| 35 | #include "system/serial_link.h" | ||
| 36 | #include "led.h" | ||
| 37 | #include "animations.h" | ||
| 38 | |||
| 39 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); | ||
| 40 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); | ||
| 41 | |||
| 42 | static bool initial_update = true; | ||
| 43 | |||
| 44 | // Feel free to modify the animations below, or even add new ones if needed | ||
| 45 | |||
| 46 | static keyframe_animation_t lcd_layer_display = { | ||
| 47 | .num_frames = 1, | ||
| 48 | .loop = false, | ||
| 49 | .frame_lengths = {gfxMillisecondsToTicks(0)}, | ||
| 50 | .frame_functions = {lcd_keyframe_display_layer_and_led_states} | ||
| 51 | }; | ||
| 52 | |||
| 53 | // The color animation animates the LCD color when you change layers | ||
| 54 | static keyframe_animation_t color_animation = { | ||
| 55 | .num_frames = 2, | ||
| 56 | .loop = false, | ||
| 57 | // Note that there's a 200 ms no-operation frame, | ||
| 58 | // this prevents the color from changing when activating the layer | ||
| 59 | // momentarily | ||
| 60 | .frame_lengths = {gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(500)}, | ||
| 61 | .frame_functions = {keyframe_no_operation, backlight_keyframe_animate_color}, | ||
| 62 | }; | ||
| 63 | |||
| 64 | void initialize_user_visualizer(visualizer_state_t* state) { | ||
| 65 | // The brightness will be dynamically adjustable in the future | ||
| 66 | // But for now, change it here. | ||
| 67 | lcd_backlight_brightness(130); | ||
| 68 | state->current_lcd_color = initial_color; | ||
| 69 | state->target_lcd_color = logo_background_color; | ||
| 70 | initial_update = true; | ||
| 71 | start_keyframe_animation(&default_startup_animation); | ||
| 72 | } | ||
| 73 | |||
| 74 | |||
| 75 | // This function should be implemented by the keymap visualizer | ||
| 76 | // Don't change anything else than state->target_lcd_color and state->layer_text as that's the only thing | ||
| 77 | // that the simple_visualizer assumes that you are updating | ||
| 78 | // Also make sure that the buffer passed to state->layer_text remains valid until the previous animation is | ||
| 79 | // stopped. This can be done by either double buffering it or by using constant strings | ||
| 80 | static void get_visualizer_layer_and_color(visualizer_state_t* state); | ||
| 81 | |||
| 82 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) { | ||
| 83 | // Add more tests, change the colors and layer texts here | ||
| 84 | // Usually you want to check the high bits (higher layers first) | ||
| 85 | // because that's the order layers are processed for keypresses | ||
| 86 | // You can for check for example: | ||
| 87 | // state->status.layer | ||
| 88 | // state->status.default_layer | ||
| 89 | // state->status.leds (see led.h for available statuses) | ||
| 90 | |||
| 91 | uint32_t prev_color = state->target_lcd_color; | ||
| 92 | const char* prev_layer_text = state->layer_text; | ||
| 93 | |||
| 94 | get_visualizer_layer_and_color(state); | ||
| 95 | |||
| 96 | if (initial_update || prev_color != state->target_lcd_color) { | ||
| 97 | start_keyframe_animation(&color_animation); | ||
| 98 | } | ||
| 99 | |||
| 100 | if (initial_update || prev_layer_text != state->layer_text) { | ||
| 101 | start_keyframe_animation(&lcd_layer_display); | ||
| 102 | } | ||
| 103 | // You can also stop existing animations, and start your custom ones here | ||
| 104 | // remember that you should normally have only one animation for the LCD | ||
| 105 | // and one for the background. But you can also combine them if you want. | ||
| 106 | } | ||
| 107 | |||
| 108 | void user_visualizer_suspend(visualizer_state_t* state) { | ||
| 109 | state->layer_text = "Suspending..."; | ||
| 110 | uint8_t hue = LCD_HUE(state->current_lcd_color); | ||
| 111 | uint8_t sat = LCD_SAT(state->current_lcd_color); | ||
| 112 | state->target_lcd_color = LCD_COLOR(hue, sat, 0); | ||
| 113 | start_keyframe_animation(&default_suspend_animation); | ||
| 114 | } | ||
| 115 | |||
| 116 | void user_visualizer_resume(visualizer_state_t* state) { | ||
| 117 | state->current_lcd_color = initial_color; | ||
| 118 | state->target_lcd_color = logo_background_color; | ||
| 119 | initial_update = true; | ||
| 120 | start_keyframe_animation(&default_startup_animation); | ||
| 121 | } | ||
| 122 | |||
| 123 | #endif /* KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_ */ | ||
diff --git a/keyboards/ergodox/infinity/visualizer.c b/keyboards/ergodox/infinity/visualizer.c new file mode 100644 index 000000000..a4b09a34d --- /dev/null +++ b/keyboards/ergodox/infinity/visualizer.c | |||
| @@ -0,0 +1,329 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2016 Fred Sundvik <fsundvik@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 | // Currently we are assuming that both the backlight and LCD are enabled | ||
| 19 | // But it's entirely possible to write a custom visualizer that use only | ||
| 20 | // one of them | ||
| 21 | #ifndef LCD_BACKLIGHT_ENABLE | ||
| 22 | #error This visualizer needs that LCD backlight is enabled | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #ifndef LCD_ENABLE | ||
| 26 | #error This visualizer needs that LCD is enabled | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #include "visualizer.h" | ||
| 30 | #include "visualizer_keyframes.h" | ||
| 31 | #include "lcd_keyframes.h" | ||
| 32 | #include "lcd_backlight_keyframes.h" | ||
| 33 | #include "system/serial_link.h" | ||
| 34 | #include "animations.h" | ||
| 35 | |||
| 36 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); | ||
| 37 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); | ||
| 38 | |||
| 39 | static const uint32_t led_emulation_colors[4] = { | ||
| 40 | LCD_COLOR(0, 0, 0), | ||
| 41 | LCD_COLOR(255, 255, 255), | ||
| 42 | LCD_COLOR(84, 255, 255), | ||
| 43 | LCD_COLOR(168, 255, 255), | ||
| 44 | }; | ||
| 45 | |||
| 46 | static uint32_t next_led_target_color = 0; | ||
| 47 | |||
| 48 | typedef enum { | ||
| 49 | LCD_STATE_INITIAL, | ||
| 50 | LCD_STATE_LAYER_BITMAP, | ||
| 51 | LCD_STATE_BITMAP_AND_LEDS, | ||
| 52 | } lcd_state_t; | ||
| 53 | |||
| 54 | static lcd_state_t lcd_state = LCD_STATE_INITIAL; | ||
| 55 | |||
| 56 | typedef struct { | ||
| 57 | uint8_t led_on; | ||
| 58 | uint8_t led1; | ||
| 59 | uint8_t led2; | ||
| 60 | uint8_t led3; | ||
| 61 | } visualizer_user_data_t; | ||
| 62 | |||
| 63 | // Don't access from visualization function, use the visualizer state instead | ||
| 64 | static visualizer_user_data_t user_data_keyboard = { | ||
| 65 | .led_on = 0, | ||
| 66 | .led1 = LED_BRIGHTNESS_HI, | ||
| 67 | .led2 = LED_BRIGHTNESS_HI, | ||
| 68 | .led3 = LED_BRIGHTNESS_HI, | ||
| 69 | }; | ||
| 70 | |||
| 71 | _Static_assert(sizeof(visualizer_user_data_t) <= VISUALIZER_USER_DATA_SIZE, | ||
| 72 | "Please increase the VISUALIZER_USER_DATA_SIZE"); | ||
| 73 | |||
| 74 | // Feel free to modify the animations below, or even add new ones if needed | ||
| 75 | |||
| 76 | |||
| 77 | // The color animation animates the LCD color when you change layers | ||
| 78 | static keyframe_animation_t one_led_color = { | ||
| 79 | .num_frames = 1, | ||
| 80 | .loop = false, | ||
| 81 | .frame_lengths = {gfxMillisecondsToTicks(0)}, | ||
| 82 | .frame_functions = {backlight_keyframe_set_color}, | ||
| 83 | }; | ||
| 84 | |||
| 85 | bool swap_led_target_color(keyframe_animation_t* animation, visualizer_state_t* state) { | ||
| 86 | uint32_t temp = next_led_target_color; | ||
| 87 | next_led_target_color = state->target_lcd_color; | ||
| 88 | state->target_lcd_color = temp; | ||
| 89 | return false; | ||
| 90 | } | ||
| 91 | |||
| 92 | // The color animation animates the LCD color when you change layers | ||
| 93 | static keyframe_animation_t two_led_colors = { | ||
| 94 | .num_frames = 2, | ||
| 95 | .loop = true, | ||
| 96 | .frame_lengths = {gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(0)}, | ||
| 97 | .frame_functions = {backlight_keyframe_set_color, swap_led_target_color}, | ||
| 98 | }; | ||
| 99 | |||
| 100 | // The LCD animation alternates between the layer name display and a | ||
| 101 | // bitmap that displays all active layers | ||
| 102 | static keyframe_animation_t lcd_bitmap_animation = { | ||
| 103 | .num_frames = 1, | ||
| 104 | .loop = false, | ||
| 105 | .frame_lengths = {gfxMillisecondsToTicks(0)}, | ||
| 106 | .frame_functions = {lcd_keyframe_display_layer_bitmap}, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static keyframe_animation_t lcd_bitmap_leds_animation = { | ||
| 110 | .num_frames = 2, | ||
| 111 | .loop = true, | ||
| 112 | .frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)}, | ||
| 113 | .frame_functions = {lcd_keyframe_display_layer_bitmap, lcd_keyframe_display_led_states}, | ||
| 114 | }; | ||
| 115 | |||
| 116 | void initialize_user_visualizer(visualizer_state_t* state) { | ||
| 117 | // The brightness will be dynamically adjustable in the future | ||
| 118 | // But for now, change it here. | ||
| 119 | lcd_backlight_brightness(130); | ||
| 120 | state->current_lcd_color = initial_color; | ||
| 121 | state->target_lcd_color = logo_background_color; | ||
| 122 | lcd_state = LCD_STATE_INITIAL; | ||
| 123 | start_keyframe_animation(&default_startup_animation); | ||
| 124 | } | ||
| 125 | |||
| 126 | inline bool is_led_on(visualizer_user_data_t* user_data, uint8_t num) { | ||
| 127 | return user_data->led_on & (1u << num); | ||
| 128 | } | ||
| 129 | |||
| 130 | static uint8_t get_led_index_master(visualizer_user_data_t* user_data) { | ||
| 131 | for (int i=0; i < 3; i++) { | ||
| 132 | if (is_led_on(user_data, i)) { | ||
| 133 | return i + 1; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static uint8_t get_led_index_slave(visualizer_user_data_t* user_data) { | ||
| 140 | uint8_t master_index = get_led_index_master(user_data); | ||
| 141 | if (master_index!=0) { | ||
| 142 | for (int i=master_index; i < 3; i++) { | ||
| 143 | if (is_led_on(user_data, i)) { | ||
| 144 | return i + 1; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static uint8_t get_secondary_led_index(visualizer_user_data_t* user_data) { | ||
| 153 | if (is_led_on(user_data, 0) && | ||
| 154 | is_led_on(user_data, 1) && | ||
| 155 | is_led_on(user_data, 2)) { | ||
| 156 | return 3; | ||
| 157 | } | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static uint8_t get_brightness(visualizer_user_data_t* user_data, uint8_t index) { | ||
| 162 | switch (index) { | ||
| 163 | case 1: | ||
| 164 | return user_data->led1; | ||
| 165 | case 2: | ||
| 166 | return user_data->led2; | ||
| 167 | case 3: | ||
| 168 | return user_data->led3; | ||
| 169 | } | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static void update_emulated_leds(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) { | ||
| 174 | visualizer_user_data_t* user_data_new = (visualizer_user_data_t*)state->status.user_data; | ||
| 175 | visualizer_user_data_t* user_data_old = (visualizer_user_data_t*)prev_status->user_data; | ||
| 176 | |||
| 177 | uint8_t new_index; | ||
| 178 | uint8_t old_index; | ||
| 179 | |||
| 180 | if (is_serial_link_master()) { | ||
| 181 | new_index = get_led_index_master(user_data_new); | ||
| 182 | old_index = get_led_index_master(user_data_old); | ||
| 183 | } | ||
| 184 | else { | ||
| 185 | new_index = get_led_index_slave(user_data_new); | ||
| 186 | old_index = get_led_index_slave(user_data_old); | ||
| 187 | } | ||
| 188 | uint8_t new_secondary_index = get_secondary_led_index(user_data_new); | ||
| 189 | uint8_t old_secondary_index = get_secondary_led_index(user_data_old); | ||
| 190 | |||
| 191 | uint8_t old_brightness = get_brightness(user_data_old, old_index); | ||
| 192 | uint8_t new_brightness = get_brightness(user_data_new, new_index); | ||
| 193 | |||
| 194 | uint8_t old_secondary_brightness = get_brightness(user_data_old, old_secondary_index); | ||
| 195 | uint8_t new_secondary_brightness = get_brightness(user_data_new, new_secondary_index); | ||
| 196 | |||
| 197 | if (lcd_state == LCD_STATE_INITIAL || | ||
| 198 | new_index != old_index || | ||
| 199 | new_secondary_index != old_secondary_index || | ||
| 200 | new_brightness != old_brightness || | ||
| 201 | new_secondary_brightness != old_secondary_brightness) { | ||
| 202 | |||
| 203 | if (new_secondary_index != 0) { | ||
| 204 | state->target_lcd_color = change_lcd_color_intensity( | ||
| 205 | led_emulation_colors[new_index], new_brightness); | ||
| 206 | next_led_target_color = change_lcd_color_intensity( | ||
| 207 | led_emulation_colors[new_secondary_index], new_secondary_brightness); | ||
| 208 | |||
| 209 | stop_keyframe_animation(&one_led_color); | ||
| 210 | start_keyframe_animation(&two_led_colors); | ||
| 211 | } else { | ||
| 212 | state->target_lcd_color = change_lcd_color_intensity( | ||
| 213 | led_emulation_colors[new_index], new_brightness); | ||
| 214 | stop_keyframe_animation(&two_led_colors); | ||
| 215 | start_keyframe_animation(&one_led_color); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | static void update_lcd_text(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) { | ||
| 221 | if (state->status.leds) { | ||
| 222 | if (lcd_state != LCD_STATE_BITMAP_AND_LEDS || | ||
| 223 | state->status.leds != prev_status->leds || | ||
| 224 | state->status.layer != prev_status->layer || | ||
| 225 | state->status.default_layer != prev_status->default_layer) { | ||
| 226 | |||
| 227 | // NOTE: that it doesn't matter if the animation isn't playing, stop will do nothing in that case | ||
| 228 | stop_keyframe_animation(&lcd_bitmap_animation); | ||
| 229 | |||
| 230 | lcd_state = LCD_STATE_BITMAP_AND_LEDS; | ||
| 231 | // For information: | ||
| 232 | // The logic in this function makes sure that this doesn't happen, but if you call start on an | ||
| 233 | // animation that is already playing it will be restarted. | ||
| 234 | start_keyframe_animation(&lcd_bitmap_leds_animation); | ||
| 235 | } | ||
| 236 | } else { | ||
| 237 | if (lcd_state != LCD_STATE_LAYER_BITMAP || | ||
| 238 | state->status.layer != prev_status->layer || | ||
| 239 | state->status.default_layer != prev_status->default_layer) { | ||
| 240 | |||
| 241 | stop_keyframe_animation(&lcd_bitmap_leds_animation); | ||
| 242 | |||
| 243 | lcd_state = LCD_STATE_LAYER_BITMAP; | ||
| 244 | start_keyframe_animation(&lcd_bitmap_animation); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) { | ||
| 250 | // Check the status here to start and stop animations | ||
| 251 | // You might have to save some state, like the current animation here so that you can start the right | ||
| 252 | // This function is called every time the status changes | ||
| 253 | |||
| 254 | // NOTE that this is called from the visualizer thread, so don't access anything else outside the status | ||
| 255 | // This is also important because the slave won't have access to the active layer for example outside the | ||
| 256 | // status. | ||
| 257 | |||
| 258 | update_emulated_leds(state, prev_status); | ||
| 259 | update_lcd_text(state, prev_status); | ||
| 260 | |||
| 261 | } | ||
| 262 | |||
| 263 | void user_visualizer_suspend(visualizer_state_t* state) { | ||
| 264 | state->layer_text = "Suspending..."; | ||
| 265 | uint8_t hue = LCD_HUE(state->current_lcd_color); | ||
| 266 | uint8_t sat = LCD_SAT(state->current_lcd_color); | ||
| 267 | state->target_lcd_color = LCD_COLOR(hue, sat, 0); | ||
| 268 | start_keyframe_animation(&default_suspend_animation); | ||
| 269 | } | ||
| 270 | |||
| 271 | void user_visualizer_resume(visualizer_state_t* state) { | ||
| 272 | state->current_lcd_color = initial_color; | ||
| 273 | state->target_lcd_color = logo_background_color; | ||
| 274 | lcd_state = LCD_STATE_INITIAL; | ||
| 275 | start_keyframe_animation(&default_startup_animation); | ||
| 276 | } | ||
| 277 | |||
| 278 | void ergodox_board_led_on(void){ | ||
| 279 | // No board led support | ||
| 280 | } | ||
| 281 | |||
| 282 | void ergodox_right_led_1_on(void){ | ||
| 283 | user_data_keyboard.led_on |= (1u << 0); | ||
| 284 | visualizer_set_user_data(&user_data_keyboard); | ||
| 285 | } | ||
| 286 | |||
| 287 | void ergodox_right_led_2_on(void){ | ||
| 288 | user_data_keyboard.led_on |= (1u << 1); | ||
| 289 | visualizer_set_user_data(&user_data_keyboard); | ||
| 290 | } | ||
| 291 | |||
| 292 | void ergodox_right_led_3_on(void){ | ||
| 293 | user_data_keyboard.led_on |= (1u << 2); | ||
| 294 | visualizer_set_user_data(&user_data_keyboard); | ||
| 295 | } | ||
| 296 | |||
| 297 | void ergodox_board_led_off(void){ | ||
| 298 | // No board led support | ||
| 299 | } | ||
| 300 | |||
| 301 | void ergodox_right_led_1_off(void){ | ||
| 302 | user_data_keyboard.led_on &= ~(1u << 0); | ||
| 303 | visualizer_set_user_data(&user_data_keyboard); | ||
| 304 | } | ||
| 305 | |||
| 306 | void ergodox_right_led_2_off(void){ | ||
| 307 | user_data_keyboard.led_on &= ~(1u << 1); | ||
| 308 | visualizer_set_user_data(&user_data_keyboard); | ||
| 309 | } | ||
| 310 | |||
| 311 | void ergodox_right_led_3_off(void){ | ||
| 312 | user_data_keyboard.led_on &= ~(1u << 2); | ||
| 313 | visualizer_set_user_data(&user_data_keyboard); | ||
| 314 | } | ||
| 315 | |||
| 316 | void ergodox_right_led_1_set(uint8_t n) { | ||
| 317 | user_data_keyboard.led1 = n; | ||
| 318 | visualizer_set_user_data(&user_data_keyboard); | ||
| 319 | } | ||
| 320 | |||
| 321 | void ergodox_right_led_2_set(uint8_t n) { | ||
| 322 | user_data_keyboard.led2 = n; | ||
| 323 | visualizer_set_user_data(&user_data_keyboard); | ||
| 324 | } | ||
| 325 | |||
| 326 | void ergodox_right_led_3_set(uint8_t n) { | ||
| 327 | user_data_keyboard.led3 = n; | ||
| 328 | visualizer_set_user_data(&user_data_keyboard); | ||
| 329 | } | ||
