aboutsummaryrefslogtreecommitdiff
path: root/keyboards/ergodox/infinity
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/ergodox/infinity')
-rw-r--r--keyboards/ergodox/infinity/Makefile2
-rw-r--r--keyboards/ergodox/infinity/animations.c107
-rw-r--r--keyboards/ergodox/infinity/animations.h30
-rw-r--r--keyboards/ergodox/infinity/config.h4
-rw-r--r--keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c37
-rw-r--r--keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/board_ST7565.h80
-rw-r--r--keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c411
-rw-r--r--keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/gdisp_lld_config.h11
-rw-r--r--keyboards/ergodox/infinity/drivers/gdisp/st7565ergodox/st7565.h2
-rw-r--r--keyboards/ergodox/infinity/gfxconf.h2
-rw-r--r--keyboards/ergodox/infinity/infinity.c51
-rw-r--r--keyboards/ergodox/infinity/infinity.h71
-rw-r--r--keyboards/ergodox/infinity/matrix.c1
-rw-r--r--keyboards/ergodox/infinity/rules.mk13
-rw-r--r--keyboards/ergodox/infinity/simple_visualizer.h123
-rw-r--r--keyboards/ergodox/infinity/visualizer.c329
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 @@
1ifndef MAKEFILE_INCLUDED 1ifndef MAKEFILE_INCLUDED
2 include ../../../Makefile 2 include ../../../Makefile
3endif \ No newline at end of file 3endif
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
39keyframe_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
51keyframe_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
68keyframe_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
23extern keyframe_animation_t default_startup_animation;
24extern 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
28extern 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
30extern 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
104const 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
41static const SPIConfig spi1config = { 39static 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
55static bool_t st7565_is_data_mode = 1; 56static 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
63static 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
57static GFXINLINE void init_board(GDisplay *g) { 70static 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
73static GFXINLINE void post_init_board(GDisplay *g) { 85static 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
87static GFXINLINE void acquire_bus(GDisplay *g) { 99static 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
93static GFXINLINE void release_bus(GDisplay *g) { 103static 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
99static 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
113static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) { 108static 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
59typedef struct{ 59typedef 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
70static GFXINLINE void write_cmd(GDisplay* g, uint8_t cmd) {
71 PRIV(g)->data[PRIV(g)->data_pos++] = cmd;
72}
73
74static 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
88LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { 100LLDSPEC 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) { 152LLDSPEC 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) { 183LLDSPEC 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) { 214LLDSPEC 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
240LLDSPEC 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) { 268LLDSPEC 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
73static 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
73void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { 96void 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))
106void ergodox_board_led_on(void){ 130void ergodox_board_led_on(void){
107} 131}
108 132
133__attribute__ ((weak))
109void ergodox_right_led_1_on(void){ 134void ergodox_right_led_1_on(void){
110} 135}
111 136
137__attribute__ ((weak))
112void ergodox_right_led_2_on(void){ 138void ergodox_right_led_2_on(void){
113} 139}
114 140
141__attribute__ ((weak))
115void ergodox_right_led_3_on(void){ 142void ergodox_right_led_3_on(void){
116} 143}
117 144
118void ergodox_right_led_on(uint8_t led){ 145__attribute__ ((weak))
119}
120
121void ergodox_board_led_off(void){ 146void ergodox_board_led_off(void){
122} 147}
123 148
149__attribute__ ((weak))
124void ergodox_right_led_1_off(void){ 150void ergodox_right_led_1_off(void){
125} 151}
126 152
153__attribute__ ((weak))
127void ergodox_right_led_2_off(void){ 154void ergodox_right_led_2_off(void){
128} 155}
129 156
157__attribute__ ((weak))
130void ergodox_right_led_3_off(void){ 158void ergodox_right_led_3_off(void){
131} 159}
132 160
133void ergodox_right_led_off(uint8_t led){ 161__attribute__ ((weak))
162void ergodox_right_led_1_set(uint8_t n) {
163}
164
165__attribute__ ((weak))
166void ergodox_right_led_2_set(uint8_t n) {
167}
168
169__attribute__ ((weak))
170void 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);
7void ergodox_right_led_1_on(void); 7void ergodox_right_led_1_on(void);
8void ergodox_right_led_2_on(void); 8void ergodox_right_led_2_on(void);
9void ergodox_right_led_3_on(void); 9void ergodox_right_led_3_on(void);
10void ergodox_right_led_on(uint8_t led); 10
11inline 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
12void ergodox_board_led_off(void); 25void ergodox_board_led_off(void);
13void ergodox_right_led_1_off(void); 26void ergodox_right_led_1_off(void);
14void ergodox_right_led_2_off(void); 27void ergodox_right_led_2_off(void);
15void ergodox_right_led_3_off(void); 28void ergodox_right_led_3_off(void);
16void ergodox_right_led_off(uint8_t led); 29inline 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
18inline void ergodox_led_all_on(void) 43inline 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
34inline void ergodox_right_led_1_set(uint8_t n){ 59void ergodox_right_led_1_set(uint8_t n);
35 if (n) { 60void ergodox_right_led_2_set(uint8_t n);
36 ergodox_right_led_1_on(); 61void ergodox_right_led_3_set(uint8_t n);
37 } else {
38 ergodox_right_led_1_off();
39 }
40}
41
42inline 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
50inline 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
58inline void ergodox_right_led_set(uint8_t led, uint8_t n){ 63inline 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
66inline void ergodox_led_all_set(uint8_t n) { 77inline 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
2SRC = matrix.c \ 2SRC = 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#
60CUSTOM_MATRIX ?= yes # Custom matrix file 61CUSTOM_MATRIX ?= yes # Custom matrix file
61SERIAL_LINK_ENABLE = yes 62SERIAL_LINK_ENABLE = yes
62VISUALIZER_ENABLE ?= no #temporarily disabled to make everything compile 63VISUALIZER_ENABLE ?= yes
63LCD_ENABLE ?= yes 64LCD_ENABLE ?= yes
64LED_ENABLE ?= yes 65LED_ENABLE ?= no
65LCD_BACKLIGHT_ENABLE ?= yes 66LCD_BACKLIGHT_ENABLE ?= yes
66MIDI_ENABLE = no 67MIDI_ENABLE = no
67RGBLIGHT_ENABLE = no 68RGBLIGHT_ENABLE = no
68 69
69ifndef QUANTUM_DIR
70 include ../../../Makefile
71endif
72
73ifdef LCD_ENABLE 70ifdef LCD_ENABLE
74include $(SUBPROJECT_PATH)/drivers/gdisp/st7565ergodox/driver.mk 71include $(SUBPROJECT_PATH)/drivers/gdisp/st7565ergodox/driver.mk
75endif 72endif
76 73
77ifdef LED_ENABLE 74ifdef LED_ENABLE
78include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk 75include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk
79endif 76endif \ 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
39static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF);
40static const uint32_t initial_color = LCD_COLOR(0, 0, 0);
41
42static bool initial_update = true;
43
44// Feel free to modify the animations below, or even add new ones if needed
45
46static 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
54static 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
64void 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
80static void get_visualizer_layer_and_color(visualizer_state_t* state);
81
82void 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
108void 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
116void 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/*
2Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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
36static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF);
37static const uint32_t initial_color = LCD_COLOR(0, 0, 0);
38
39static 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
46static uint32_t next_led_target_color = 0;
47
48typedef enum {
49 LCD_STATE_INITIAL,
50 LCD_STATE_LAYER_BITMAP,
51 LCD_STATE_BITMAP_AND_LEDS,
52} lcd_state_t;
53
54static lcd_state_t lcd_state = LCD_STATE_INITIAL;
55
56typedef 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
64static 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
78static 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
85bool 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
93static 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
102static 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
109static 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
116void 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
126inline bool is_led_on(visualizer_user_data_t* user_data, uint8_t num) {
127 return user_data->led_on & (1u << num);
128}
129
130static 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
139static 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
152static 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
161static 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
173static 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
220static 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
249void 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
263void 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
271void 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
278void ergodox_board_led_on(void){
279 // No board led support
280}
281
282void ergodox_right_led_1_on(void){
283 user_data_keyboard.led_on |= (1u << 0);
284 visualizer_set_user_data(&user_data_keyboard);
285}
286
287void ergodox_right_led_2_on(void){
288 user_data_keyboard.led_on |= (1u << 1);
289 visualizer_set_user_data(&user_data_keyboard);
290}
291
292void ergodox_right_led_3_on(void){
293 user_data_keyboard.led_on |= (1u << 2);
294 visualizer_set_user_data(&user_data_keyboard);
295}
296
297void ergodox_board_led_off(void){
298 // No board led support
299}
300
301void ergodox_right_led_1_off(void){
302 user_data_keyboard.led_on &= ~(1u << 0);
303 visualizer_set_user_data(&user_data_keyboard);
304}
305
306void ergodox_right_led_2_off(void){
307 user_data_keyboard.led_on &= ~(1u << 1);
308 visualizer_set_user_data(&user_data_keyboard);
309}
310
311void ergodox_right_led_3_off(void){
312 user_data_keyboard.led_on &= ~(1u << 2);
313 visualizer_set_user_data(&user_data_keyboard);
314}
315
316void ergodox_right_led_1_set(uint8_t n) {
317 user_data_keyboard.led1 = n;
318 visualizer_set_user_data(&user_data_keyboard);
319}
320
321void ergodox_right_led_2_set(uint8_t n) {
322 user_data_keyboard.led2 = n;
323 visualizer_set_user_data(&user_data_keyboard);
324}
325
326void ergodox_right_led_3_set(uint8_t n) {
327 user_data_keyboard.led3 = n;
328 visualizer_set_user_data(&user_data_keyboard);
329}