aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-07-07 09:59:33 -0400
committerGitHub <noreply@github.com>2016-07-07 09:59:33 -0400
commitad43d450ca1b988d196da80e2a745f45f24068f6 (patch)
treea479c21240dba88cd593e85cac6926b17924984d
parent589df84d6cd19ad7d776cc19bcddade1cd178ddc (diff)
parentcaedec92d2c22480313c43a364408fb920c55364 (diff)
downloadqmk_firmware-ad43d450ca1b988d196da80e2a745f45f24068f6.tar.gz
qmk_firmware-ad43d450ca1b988d196da80e2a745f45f24068f6.zip
Merge pull request #490 from fredizzimo/integrate_visualizer
Integrate visualizer for ChibiOS and Infinity Ergodox
-rw-r--r--.gitmodules3
-rw-r--r--Makefile15
-rw-r--r--keyboards/infinity_ergodox/Makefile12
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/board_IS31FL3731C.h113
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/driver.mk2
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c333
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_lld_config.h36
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/driver.mk2
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/emulator_lcd.c10
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/emulator_led/driver.mk2
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/emulator_led/emulator_led.c10
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/board_ST7565.h127
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/driver.mk2
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c292
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_config.h26
-rw-r--r--keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/st7565.h37
-rw-r--r--keyboards/infinity_ergodox/gfxconf.h331
-rw-r--r--keyboards/infinity_ergodox/infinity_ergodox.c65
-rw-r--r--keyboards/infinity_ergodox/keymaps/default/visualizer.c168
m---------lib/ugfx0
-rw-r--r--quantum/visualizer/led_test.c4
-rw-r--r--quantum/visualizer/visualizer.c14
-rw-r--r--quantum/visualizer/visualizer.h2
-rw-r--r--quantum/visualizer/visualizer.mk36
-rw-r--r--tmk_core/common/keyboard.c8
-rw-r--r--tmk_core/protocol/chibios/main.c15
26 files changed, 1626 insertions, 39 deletions
diff --git a/.gitmodules b/.gitmodules
index 1576b8dc0..7e3c92d03 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
4[submodule "lib/chibios-contrib"] 4[submodule "lib/chibios-contrib"]
5 path = lib/chibios-contrib 5 path = lib/chibios-contrib
6 url = https://github.com/ChibiOS/ChibiOS-Contrib.git 6 url = https://github.com/ChibiOS/ChibiOS-Contrib.git
7[submodule "lib/ugfx"]
8 path = lib/ugfx
9 url = https://bitbucket.org/Tectu/ugfx
diff --git a/Makefile b/Makefile
index 7c00ce2cc..a7a10bf32 100644
--- a/Makefile
+++ b/Makefile
@@ -218,14 +218,6 @@ ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
218 VAPTH += $(SERIAL_PATH) 218 VAPTH += $(SERIAL_PATH)
219endif 219endif
220 220
221ifeq ($(MASTER),right)
222 OPT_DEFS += -DMASTER_IS_ON_RIGHT
223else
224 ifneq ($(MASTER),left)
225$(error MASTER does not have a valid value(left/right))
226 endif
227endif
228
229# Optimize size but this may cause error "relocation truncated to fit" 221# Optimize size but this may cause error "relocation truncated to fit"
230#EXTRALDFLAGS = -Wl,--relax 222#EXTRALDFLAGS = -Wl,--relax
231 223
@@ -257,10 +249,17 @@ ifeq ($(PLATFORM),AVR)
257else ifeq ($(PLATFORM),CHIBIOS) 249else ifeq ($(PLATFORM),CHIBIOS)
258 include $(TMK_PATH)/protocol/chibios.mk 250 include $(TMK_PATH)/protocol/chibios.mk
259 include $(TMK_PATH)/chibios.mk 251 include $(TMK_PATH)/chibios.mk
252 OPT_OS = chibios
260else 253else
261 $(error Unknown platform) 254 $(error Unknown platform)
262endif 255endif
263 256
257ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
258 VISUALIZER_DIR = $(QUANTUM_DIR)/visualizer
259 VISUALIZER_PATH = $(QUANTUM_PATH)/visualizer
260 include $(VISUALIZER_PATH)/visualizer.mk
261endif
262
264include $(TMK_PATH)/rules.mk 263include $(TMK_PATH)/rules.mk
265 264
266GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S") 265GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
diff --git a/keyboards/infinity_ergodox/Makefile b/keyboards/infinity_ergodox/Makefile
index efa32e037..7edc03d8c 100644
--- a/keyboards/infinity_ergodox/Makefile
+++ b/keyboards/infinity_ergodox/Makefile
@@ -67,6 +67,18 @@ SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
67NKRO_ENABLE ?= yes # USB Nkey Rollover 67NKRO_ENABLE ?= yes # USB Nkey Rollover
68CUSTOM_MATRIX ?= yes # Custom matrix file 68CUSTOM_MATRIX ?= yes # Custom matrix file
69SERIAL_LINK_ENABLE = yes 69SERIAL_LINK_ENABLE = yes
70VISUALIZER_ENABLE ?= yes
71LCD_ENABLE ?= yes
72LED_ENABLE ?= yes
73LCD_BACKLIGHT_ENABLE ?= yes
74
75ifdef LCD_ENABLE
76include drivers/gdisp/st7565ergodox/driver.mk
77endif
78
79ifdef LED_ENABLE
80include drivers/gdisp/IS31FL3731C/driver.mk
81endif
70 82
71ifndef QUANTUM_DIR 83ifndef QUANTUM_DIR
72 include ../../Makefile 84 include ../../Makefile
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/board_IS31FL3731C.h b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/board_IS31FL3731C.h
new file mode 100644
index 000000000..2ea73f1fb
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/board_IS31FL3731C.h
@@ -0,0 +1,113 @@
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#ifndef _GDISP_LLD_BOARD_H
19#define _GDISP_LLD_BOARD_H
20
21static const I2CConfig i2ccfg = {
22 400000 // clock speed (Hz); 400kHz max for IS31
23};
24
25#define GDISP_SCREEN_WIDTH 7
26#define GDISP_SCREEN_HEIGHT 7
27
28static const uint8_t led_mask[] = {
29 0xFF, 0x00, /* C1-1 -> C1-16 */
30 0xFF, 0x00, /* C2-1 -> C2-16 */
31 0xFF, 0x00, /* C3-1 -> C3-16 */
32 0xFF, 0x00, /* C4-1 -> C4-16 */
33 0x3F, 0x00, /* C5-1 -> C5-16 */
34 0x00, 0x00, /* C6-1 -> C6-16 */
35 0x00, 0x00, /* C7-1 -> C7-16 */
36 0x00, 0x00, /* C8-1 -> C8-16 */
37 0x00, 0x00, /* C9-1 -> C9-16 */
38};
39
40// The address of the LED
41#define LA(c, r) (c + r * 16 )
42// Need to be an address that is not mapped, but inside the range of the controller matrix
43#define NA LA(8, 8)
44
45// The numbers in the comments are the led numbers DXX on the PCB
46// The mapping is taken from the schematic of left hand side
47static const uint8_t led_mapping[GDISP_SCREEN_HEIGHT][GDISP_SCREEN_WIDTH] = {
48// 45 44 43 42 41 40 39
49 { LA(1, 1), LA(1, 0), LA(0, 4), LA(0, 3), LA(0, 2), LA(0, 1), LA(0, 0)},
50// 52 51 50 49 48 47 46
51 { LA(2, 3), LA(2, 2), LA(2, 1), LA(2, 0), LA(1, 4), LA(1, 3), LA(1, 2) },
52// 58 57 56 55 54 53 N/A
53 { LA(3, 4), LA(3, 3), LA(3, 2), LA(3, 1), LA(3, 0), LA(2, 4), NA },
54// 67 66 65 64 63 62 61
55 { LA(5, 3), LA(5, 2), LA(5, 1), LA(5, 0), LA(4, 4), LA(4, 3), LA(4, 2) },
56// 76 75 74 73 72 60 59
57 { LA(7, 3), LA(7, 2), LA(7, 1), LA(7, 0), LA(6, 3), LA(4, 1), LA(4, 0) },
58// N/A N/A N/A N/A N/A N/A 68
59 { NA, NA, NA, NA, NA, NA, LA(5, 4) },
60// N/A N/A N/A N/A 71 70 69
61 { NA, NA, NA, NA, LA(6, 2), LA(6, 1), LA(6, 0) },
62};
63
64
65#define IS31_ADDR_DEFAULT 0x74 // AD connected to GND
66#define IS31_TIMEOUT 5000
67
68static GFXINLINE void init_board(GDisplay *g) {
69 (void) g;
70 /* I2C pins */
71 palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL
72 palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATIVE_2); // PTB1/I2C0/SDA
73 palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL);
74 palClearPad(GPIOB, 16);
75 /* start I2C */
76 i2cStart(&I2CD1, &i2ccfg);
77 // try high drive (from kiibohd)
78 I2CD1.i2c->C2 |= I2Cx_C2_HDRS;
79 // try glitch fixing (from kiibohd)
80 I2CD1.i2c->FLT = 4;
81}
82
83static GFXINLINE void post_init_board(GDisplay *g) {
84 (void) g;
85}
86
87static GFXINLINE const uint8_t* get_led_mask(GDisplay* g) {
88 (void) g;
89 return led_mask;
90}
91
92static GFXINLINE uint8_t get_led_address(GDisplay* g, uint16_t x, uint16_t y)
93{
94 (void) g;
95 return led_mapping[y][x];
96}
97
98static GFXINLINE void set_hardware_shutdown(GDisplay* g, bool shutdown) {
99 (void) g;
100 if(!shutdown) {
101 palSetPad(GPIOB, 16);
102 }
103 else {
104 palClearPad(GPIOB, 16);
105 }
106}
107
108static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
109 (void) g;
110 i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, data, length, 0, 0, US2ST(IS31_TIMEOUT));
111}
112
113#endif /* _GDISP_LLD_BOARD_H */
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/driver.mk b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/driver.mk
new file mode 100644
index 000000000..f32d0d868
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/driver.mk
@@ -0,0 +1,2 @@
1GFXINC += drivers/gdisp/IS31FL3731C
2GFXSRC += drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c
new file mode 100644
index 000000000..1d21f0c49
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c
@@ -0,0 +1,333 @@
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#include "gfx.h"
19
20#if GFX_USE_GDISP
21
22#define GDISP_DRIVER_VMT GDISPVMT_IS31FL3731C_ERGODOX
23#include "drivers/gdisp/IS31FL3731C/gdisp_lld_config.h"
24#include "src/gdisp/gdisp_driver.h"
25
26#include "board_IS31FL3731C.h"
27
28/*===========================================================================*/
29/* Driver local definitions. */
30/*===========================================================================*/
31
32#ifndef GDISP_SCREEN_HEIGHT
33 #define GDISP_SCREEN_HEIGHT 9
34#endif
35#ifndef GDISP_SCREEN_WIDTH
36 #define GDISP_SCREEN_WIDTH 16
37#endif
38#ifndef GDISP_INITIAL_CONTRAST
39 #define GDISP_INITIAL_CONTRAST 0
40#endif
41#ifndef GDISP_INITIAL_BACKLIGHT
42 #define GDISP_INITIAL_BACKLIGHT 100
43#endif
44
45#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0)
46
47#define IS31_ADDR_DEFAULT 0x74
48
49#define IS31_REG_CONFIG 0x00
50// bits in reg
51#define IS31_REG_CONFIG_PICTUREMODE 0x00
52#define IS31_REG_CONFIG_AUTOPLAYMODE 0x08
53#define IS31_REG_CONFIG_AUDIOPLAYMODE 0x18
54// D2:D0 bits are starting frame for autoplay mode
55
56#define IS31_REG_PICTDISP 0x01 // D2:D0 frame select for picture mode
57
58#define IS31_REG_AUTOPLAYCTRL1 0x02
59// D6:D4 number of loops (000=infty)
60// D2:D0 number of frames to be used
61
62#define IS31_REG_AUTOPLAYCTRL2 0x03 // D5:D0 delay time (*11ms)
63
64#define IS31_REG_DISPLAYOPT 0x05
65#define IS31_REG_DISPLAYOPT_INTENSITY_SAME 0x20 // same intensity for all frames
66#define IS31_REG_DISPLAYOPT_BLINK_ENABLE 0x8
67// D2:D0 bits blink period time (*0.27s)
68
69#define IS31_REG_AUDIOSYNC 0x06
70#define IS31_REG_AUDIOSYNC_ENABLE 0x1
71
72#define IS31_REG_FRAMESTATE 0x07
73
74#define IS31_REG_BREATHCTRL1 0x08
75// D6:D4 fade out time (26ms*2^i)
76// D2:D0 fade in time (26ms*2^i)
77
78#define IS31_REG_BREATHCTRL2 0x09
79#define IS31_REG_BREATHCTRL2_ENABLE 0x10
80// D2:D0 extinguish time (3.5ms*2^i)
81
82#define IS31_REG_SHUTDOWN 0x0A
83#define IS31_REG_SHUTDOWN_OFF 0x0
84#define IS31_REG_SHUTDOWN_ON 0x1
85
86#define IS31_REG_AGCCTRL 0x0B
87#define IS31_REG_ADCRATE 0x0C
88
89#define IS31_COMMANDREGISTER 0xFD
90#define IS31_FUNCTIONREG 0x0B // helpfully called 'page nine'
91#define IS31_FUNCTIONREG_SIZE 0xD
92
93#define IS31_FRAME_SIZE 0xB4
94
95#define IS31_PWM_REG 0x24
96#define IS31_PWM_SIZE 0x90
97
98#define IS31_LED_MASK_SIZE 0x12
99#define IS31_SCREEN_WIDTH 16
100
101#define IS31
102
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/*===========================================================================*/
135/* Driver local functions. */
136/*===========================================================================*/
137
138typedef struct{
139 uint8_t write_buffer_offset;
140 uint8_t write_buffer[IS31_FRAME_SIZE];
141 uint8_t frame_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH];
142 uint8_t page;
143}__attribute__((__packed__)) PrivData;
144
145// Some common routines and macros
146#define PRIV(g) ((PrivData*)g->priv)
147
148/*===========================================================================*/
149/* Driver exported functions. */
150/*===========================================================================*/
151
152static GFXINLINE void write_page(GDisplay* g, uint8_t page) {
153 uint8_t tx[2] __attribute__((aligned(2)));
154 tx[0] = IS31_COMMANDREGISTER;
155 tx[1] = page;
156 write_data(g, tx, 2);
157}
158
159static GFXINLINE void write_register(GDisplay* g, uint8_t page, uint8_t reg, uint8_t data) {
160 uint8_t tx[2] __attribute__((aligned(2)));
161 tx[0] = reg;
162 tx[1] = data;
163 write_page(g, page);
164 write_data(g, tx, 2);
165}
166
167static GFXINLINE void write_ram(GDisplay *g, uint8_t page, uint16_t offset, uint16_t length) {
168 PRIV(g)->write_buffer_offset = offset;
169 write_page(g, page);
170 write_data(g, (uint8_t*)PRIV(g), length + 1);
171}
172
173LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
174 // The private area is the display surface.
175 g->priv = gfxAlloc(sizeof(PrivData));
176 __builtin_memset(PRIV(g), 0, sizeof(PrivData));
177 PRIV(g)->page = 0;
178
179 // Initialise the board interface
180 init_board(g);
181 gfxSleepMilliseconds(10);
182
183 // zero function page, all registers (assuming full_page is all zeroes)
184 write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE);
185 set_hardware_shutdown(g, false);
186 gfxSleepMilliseconds(10);
187 // software shutdown
188 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF);
189 gfxSleepMilliseconds(10);
190 // zero function page, all registers
191 write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE);
192 gfxSleepMilliseconds(10);
193
194
195 // zero all LED registers on all 8 pages, and enable the mask
196 __builtin_memcpy(PRIV(g)->write_buffer, get_led_mask(g), IS31_LED_MASK_SIZE);
197 for(uint8_t i=0; i<8; i++) {
198 write_ram(g, i, 0, IS31_FRAME_SIZE);
199 gfxSleepMilliseconds(1);
200 }
201
202 // software shutdown disable (i.e. turn stuff on)
203 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON);
204 gfxSleepMilliseconds(10);
205
206 // Finish Init
207 post_init_board(g);
208
209 /* Initialise the GDISP structure */
210 g->g.Width = GDISP_SCREEN_WIDTH;
211 g->g.Height = GDISP_SCREEN_HEIGHT;
212 g->g.Orientation = GDISP_ROTATE_0;
213 g->g.Powermode = powerOn;
214 g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
215 g->g.Contrast = GDISP_INITIAL_CONTRAST;
216 return TRUE;
217}
218
219#if GDISP_HARDWARE_FLUSH
220 LLDSPEC void gdisp_lld_flush(GDisplay *g) {
221 // Don't flush if we don't need it.
222 if (!(g->flags & GDISP_FLG_NEEDFLUSH))
223 return;
224
225 PRIV(g)->page++;
226 PRIV(g)->page %= 2;
227 // TODO: some smarter algorithm for this
228 // We should run only one physical page at a time
229 // This way we don't need to send so much data, and
230 // we could use slightly less memory
231 uint8_t* src = PRIV(g)->frame_buffer;
232 for (int y=0;y<GDISP_SCREEN_HEIGHT;y++) {
233 for (int x=0;x<GDISP_SCREEN_WIDTH;x++) {
234 PRIV(g)->write_buffer[get_led_address(g, x, y)]=cie[*src];
235 ++src;
236 }
237 }
238 write_ram(g, PRIV(g)->page, IS31_PWM_REG, IS31_PWM_SIZE);
239 gfxSleepMilliseconds(1);
240 write_register(g, IS31_FUNCTIONREG, IS31_REG_PICTDISP, PRIV(g)->page);
241
242 g->flags &= ~GDISP_FLG_NEEDFLUSH;
243 }
244#endif
245
246#if GDISP_HARDWARE_DRAWPIXEL
247 LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
248 coord_t x, y;
249
250 switch(g->g.Orientation) {
251 default:
252 case GDISP_ROTATE_0:
253 x = g->p.x;
254 y = g->p.y;
255 break;
256 case GDISP_ROTATE_180:
257 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
258 y = g->p.y;
259 break;
260 }
261 PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x] = gdispColor2Native(g->p.color);
262 g->flags |= GDISP_FLG_NEEDFLUSH;
263 }
264#endif
265
266#if GDISP_HARDWARE_PIXELREAD
267 LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
268 coord_t x, y;
269
270 switch(g->g.Orientation) {
271 default:
272 case GDISP_ROTATE_0:
273 x = g->p.x;
274 y = g->p.y;
275 break;
276 case GDISP_ROTATE_180:
277 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
278 y = g->p.y;
279 break;
280 }
281 return gdispNative2Color(PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x]);
282 }
283#endif
284
285#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
286 LLDSPEC void gdisp_lld_control(GDisplay *g) {
287 switch(g->p.x) {
288 case GDISP_CONTROL_POWER:
289 if (g->g.Powermode == (powermode_t)g->p.ptr)
290 return;
291 switch((powermode_t)g->p.ptr) {
292 case powerOff:
293 case powerSleep:
294 case powerDeepSleep:
295 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF);
296 break;
297 case powerOn:
298 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON);
299 break;
300 default:
301 return;
302 }
303 g->g.Powermode = (powermode_t)g->p.ptr;
304 return;
305
306 case GDISP_CONTROL_ORIENTATION:
307 if (g->g.Orientation == (orientation_t)g->p.ptr)
308 return;
309 switch((orientation_t)g->p.ptr) {
310 /* Rotation is handled by the drawing routines */
311 case GDISP_ROTATE_0:
312 case GDISP_ROTATE_180:
313 g->g.Height = GDISP_SCREEN_HEIGHT;
314 g->g.Width = GDISP_SCREEN_WIDTH;
315 break;
316 case GDISP_ROTATE_90:
317 case GDISP_ROTATE_270:
318 g->g.Height = GDISP_SCREEN_WIDTH;
319 g->g.Width = GDISP_SCREEN_HEIGHT;
320 break;
321 default:
322 return;
323 }
324 g->g.Orientation = (orientation_t)g->p.ptr;
325 return;
326
327 case GDISP_CONTROL_CONTRAST:
328 return;
329 }
330 }
331#endif // GDISP_NEED_CONTROL
332
333#endif // GFX_USE_GDISP
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_lld_config.h b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_lld_config.h
new file mode 100644
index 000000000..bb28ad775
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/IS31FL3731C/gdisp_lld_config.h
@@ -0,0 +1,36 @@
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#ifndef _GDISP_LLD_CONFIG_H
19#define _GDISP_LLD_CONFIG_H
20
21#if GFX_USE_GDISP
22
23/*===========================================================================*/
24/* Driver hardware support. */
25/*===========================================================================*/
26
27#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing
28#define GDISP_HARDWARE_DRAWPIXEL TRUE
29#define GDISP_HARDWARE_PIXELREAD TRUE
30#define GDISP_HARDWARE_CONTROL TRUE
31
32#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_GRAY256
33
34#endif /* GFX_USE_GDISP */
35
36#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/driver.mk b/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/driver.mk
new file mode 100644
index 000000000..16c3f80f5
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/driver.mk
@@ -0,0 +1,2 @@
1GFXINC += drivers/gdisp/emulator_lcd
2GFXSRC += drivers/gdisp/emulator_lcd/emulator_lcd.c
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/emulator_lcd.c b/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/emulator_lcd.c
new file mode 100644
index 000000000..babfe2b36
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/emulator_lcd/emulator_lcd.c
@@ -0,0 +1,10 @@
1#define GDISP_DRIVER_VMT GDISPVMT_EMULATOR_LCD_ERGODOX
2#define GDISP_HARDWARE_DRAWPIXEL TRUE
3#define GDISP_HARDWARE_PIXELREAD TRUE
4#define GDISP_HARDWARE_CONTROL TRUE
5#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO
6#define GDISP_SCREEN_WIDTH 128
7#define GDISP_SCREEN_HEIGHT 32
8#define ROTATE_180_IS_FLIP
9
10#include "emulator/emulator_driver_impl.h"
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/driver.mk b/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/driver.mk
new file mode 100644
index 000000000..255434432
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/driver.mk
@@ -0,0 +1,2 @@
1GFXINC += drivers/gdisp/emulator_led
2GFXSRC += drivers/gdisp/emulator_led/emulator_led.c
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/emulator_led.c b/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/emulator_led.c
new file mode 100644
index 000000000..b0ebcdc47
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/emulator_led/emulator_led.c
@@ -0,0 +1,10 @@
1#define GDISP_DRIVER_VMT GDISPVMT_EMULATOR_LED_ERGODOX
2#define GDISP_HARDWARE_DRAWPIXEL TRUE
3#define GDISP_HARDWARE_PIXELREAD TRUE
4#define GDISP_HARDWARE_CONTROL TRUE
5#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO
6#define GDISP_SCREEN_WIDTH 7
7#define GDISP_SCREEN_HEIGHT 7
8#define ROTATE_180_IS_FLIP
9
10#include "emulator/emulator_driver_impl.h"
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/board_ST7565.h b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/board_ST7565.h
new file mode 100644
index 000000000..290571ce5
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/board_ST7565.h
@@ -0,0 +1,127 @@
1/*
2 * This file is subject to the terms of the GFX License. If a copy of
3 * the license was not distributed with this file, you can obtain one at:
4 *
5 * http://ugfx.org/license.html
6 */
7
8#ifndef _GDISP_LLD_BOARD_H
9#define _GDISP_LLD_BOARD_H
10
11#include "print.h"
12
13#define ST7565_LCD_BIAS ST7565_LCD_BIAS_9 // actually 6
14#define ST7565_ADC ST7565_ADC_NORMAL
15#define ST7565_COM_SCAN ST7565_COM_SCAN_DEC
16#define ST7565_PAGE_ORDER 0,1,2,3
17/*
18 * Custom page order for several LCD boards, e.g. HEM12864-99
19 * #define ST7565_PAGE_ORDER 4,5,6,7,0,1,2,3
20 */
21
22#define ST7565_GPIOPORT GPIOC
23#define ST7565_PORT PORTC
24#define ST7565_A0_PIN 7
25#define ST7565_RST_PIN 8
26#define ST7565_MOSI_PIN 6
27#define ST7565_SLCK_PIN 5
28#define ST7565_SS_PIN 4
29
30#define palSetPadModeRaw(portname, bits) \
31 ST7565_PORT->PCR[ST7565_##portname##_PIN] = bits
32
33#define palSetPadModeNamed(portname, portmode) \
34 palSetPadMode(ST7565_GPIOPORT, ST7565_##portname##_PIN, portmode)
35
36#define ST7565_SPI_MODE PORTx_PCRn_DSE | PORTx_PCRn_MUX(2)
37// DSPI Clock and Transfer Attributes
38// Frame Size: 8 bits
39// MSB First
40// CLK Low by default
41static const SPIConfig spi1config = {
42 NULL,
43 /* HW dependent part.*/
44 ST7565_GPIOPORT,
45 ST7565_SS_PIN,
46 SPIx_CTARn_FMSZ(7)
47 | SPIx_CTARn_ASC(7)
48 | SPIx_CTARn_DT(7)
49 | SPIx_CTARn_CSSCK(7)
50 | SPIx_CTARn_PBR(0)
51 | SPIx_CTARn_BR(7)
52 //SPI_CR1_BR_0
53};
54
55static bool_t st7565_is_data_mode = 1;
56
57static GFXINLINE void init_board(GDisplay *g) {
58 (void) g;
59 palSetPadModeNamed(A0, PAL_MODE_OUTPUT_PUSHPULL);
60 palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN);
61 st7565_is_data_mode = 1;
62 palSetPadModeNamed(RST, PAL_MODE_OUTPUT_PUSHPULL);
63 palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN);
64 palSetPadModeRaw(MOSI, ST7565_SPI_MODE);
65 palSetPadModeRaw(SLCK, ST7565_SPI_MODE);
66 palSetPadModeRaw(SS, ST7565_SPI_MODE);
67
68 spiInit();
69 spiStart(&SPID1, &spi1config);
70 spiSelect(&SPID1);
71}
72
73static GFXINLINE void post_init_board(GDisplay *g) {
74 (void) g;
75}
76
77static GFXINLINE void setpin_reset(GDisplay *g, bool_t state) {
78 (void) g;
79 if (state) {
80 palClearPad(ST7565_GPIOPORT, ST7565_RST_PIN);
81 }
82 else {
83 palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN);
84 }
85}
86
87static GFXINLINE void acquire_bus(GDisplay *g) {
88 (void) g;
89 // Only the LCD is using the SPI bus, so no need to acquire
90 // spiAcquireBus(&SPID1);
91}
92
93static GFXINLINE void release_bus(GDisplay *g) {
94 (void) g;
95 // Only the LCD is using the SPI bus, so no need to release
96 //spiReleaseBus(&SPID1);
97}
98
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
113static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
114 (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);
125}
126
127#endif /* _GDISP_LLD_BOARD_H */
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/driver.mk b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/driver.mk
new file mode 100644
index 000000000..889a1a031
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/driver.mk
@@ -0,0 +1,2 @@
1GFXINC += drivers/gdisp/st7565ergodox
2GFXSRC += drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c
new file mode 100644
index 000000000..c33aea81a
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c
@@ -0,0 +1,292 @@
1/*
2 * This file is subject to the terms of the GFX License. If a copy of
3 * the license was not distributed with this file, you can obtain one at:
4 *
5 * http://ugfx.org/license.html
6 */
7
8#include "gfx.h"
9
10#if GFX_USE_GDISP
11
12#define GDISP_DRIVER_VMT GDISPVMT_ST7565_ERGODOX
13#include "drivers/gdisp/st7565ergodox/gdisp_lld_config.h"
14#include "src/gdisp/gdisp_driver.h"
15
16#include "board_ST7565.h"
17
18/*===========================================================================*/
19/* Driver local definitions. */
20/*===========================================================================*/
21
22#ifndef GDISP_SCREEN_HEIGHT
23 #define GDISP_SCREEN_HEIGHT 32
24#endif
25#ifndef GDISP_SCREEN_WIDTH
26 #define GDISP_SCREEN_WIDTH 128
27#endif
28#ifndef GDISP_INITIAL_CONTRAST
29 #define GDISP_INITIAL_CONTRAST 0
30#endif
31#ifndef GDISP_INITIAL_BACKLIGHT
32 #define GDISP_INITIAL_BACKLIGHT 100
33#endif
34
35#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0)
36
37#include "drivers/gdisp/st7565ergodox/st7565.h"
38
39/*===========================================================================*/
40/* Driver config defaults for backward compatibility. */
41/*===========================================================================*/
42#ifndef ST7565_LCD_BIAS
43 #define ST7565_LCD_BIAS ST7565_LCD_BIAS_7
44#endif
45#ifndef ST7565_ADC
46 #define ST7565_ADC ST7565_ADC_NORMAL
47#endif
48#ifndef ST7565_COM_SCAN
49 #define ST7565_COM_SCAN ST7565_COM_SCAN_INC
50#endif
51#ifndef ST7565_PAGE_ORDER
52 #define ST7565_PAGE_ORDER 0,1,2,3
53#endif
54
55/*===========================================================================*/
56/* Driver local functions. */
57/*===========================================================================*/
58
59typedef struct{
60 bool_t buffer2;
61 uint8_t ram[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8];
62}PrivData;
63
64// Some common routines and macros
65#define PRIV(g) ((PrivData*)g->priv)
66#define RAM(g) (PRIV(g)->ram)
67#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); }
69
70// Some common routines and macros
71#define delay(us) gfxSleepMicroseconds(us)
72#define delay_ms(ms) gfxSleepMilliseconds(ms)
73
74#define xyaddr(x, y) ((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
75#define xybit(y) (1<<((y)&7))
76
77/*===========================================================================*/
78/* Driver exported functions. */
79/*===========================================================================*/
80
81/*
82 * As this controller can't update on a pixel boundary we need to maintain the
83 * the entire display surface in memory so that we can do the necessary bit
84 * operations. Fortunately it is a small display in monochrome.
85 * 64 * 128 / 8 = 1024 bytes.
86 */
87
88LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
89 // The private area is the display surface.
90 g->priv = gfxAlloc(sizeof(PrivData));
91 PRIV(g)->buffer2 = false;
92
93 // Initialise the board interface
94 init_board(g);
95
96 // Hardware reset
97 setpin_reset(g, TRUE);
98 gfxSleepMilliseconds(20);
99 setpin_reset(g, FALSE);
100 gfxSleepMilliseconds(20);
101
102 acquire_bus(g);
103 write_cmd(g, ST7565_DISPLAY_OFF);
104 write_cmd(g, ST7565_LCD_BIAS);
105 write_cmd(g, ST7565_ADC);
106 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
116 // turn on voltage regulator (VC=1, VR=1, VF=0)
117 write_cmd(g, ST7565_POWER_CONTROL | 0x06);
118 delay_ms(50);
119
120 // turn on voltage follower (VC=1, VR=1, VF=1)
121 write_cmd(g, ST7565_POWER_CONTROL | 0x07);
122 delay_ms(50);
123
124 write_cmd(g, 0xE2);
125 write_cmd(g, ST7565_COM_SCAN);
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
132 write_cmd(g, ST7565_RMW);
133
134 // Finish Init
135 post_init_board(g);
136
137 // Release the bus
138 release_bus(g);
139
140 /* Initialise the GDISP structure */
141 g->g.Width = GDISP_SCREEN_WIDTH;
142 g->g.Height = GDISP_SCREEN_HEIGHT;
143 g->g.Orientation = GDISP_ROTATE_0;
144 g->g.Powermode = powerOn;
145 g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
146 g->g.Contrast = GDISP_INITIAL_CONTRAST;
147 return TRUE;
148}
149
150#if GDISP_HARDWARE_FLUSH
151 LLDSPEC void gdisp_lld_flush(GDisplay *g) {
152 unsigned p;
153
154 // Don't flush if we don't need it.
155 if (!(g->flags & GDISP_FLG_NEEDFLUSH))
156 return;
157
158 acquire_bus(g);
159 unsigned dstOffset = (PRIV(g)->buffer2 ? 4 : 0);
160 for (p = 0; p < 4; p++) {
161 write_cmd(g, ST7565_PAGE | (p + dstOffset));
162 write_cmd(g, ST7565_COLUMN_MSB | 0);
163 write_cmd(g, ST7565_COLUMN_LSB | 0);
164 write_cmd(g, ST7565_RMW);
165 write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
166 }
167 unsigned line = (PRIV(g)->buffer2 ? 32 : 0);
168 write_cmd(g, ST7565_START_LINE | line);
169 PRIV(g)->buffer2 = !PRIV(g)->buffer2;
170 release_bus(g);
171
172 g->flags &= ~GDISP_FLG_NEEDFLUSH;
173 }
174#endif
175
176#if GDISP_HARDWARE_DRAWPIXEL
177 LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
178 coord_t x, y;
179
180 switch(g->g.Orientation) {
181 default:
182 case GDISP_ROTATE_0:
183 x = g->p.x;
184 y = g->p.y;
185 break;
186 case GDISP_ROTATE_90:
187 x = g->p.y;
188 y = GDISP_SCREEN_HEIGHT-1 - g->p.x;
189 break;
190 case GDISP_ROTATE_180:
191 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
192 y = GDISP_SCREEN_HEIGHT-1 - g->p.y;
193 break;
194 case GDISP_ROTATE_270:
195 x = GDISP_SCREEN_HEIGHT-1 - g->p.y;
196 y = g->p.x;
197 break;
198 }
199 if (gdispColor2Native(g->p.color) != Black)
200 RAM(g)[xyaddr(x, y)] |= xybit(y);
201 else
202 RAM(g)[xyaddr(x, y)] &= ~xybit(y);
203 g->flags |= GDISP_FLG_NEEDFLUSH;
204 }
205#endif
206
207#if GDISP_HARDWARE_PIXELREAD
208 LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
209 coord_t x, y;
210
211 switch(g->g.Orientation) {
212 default:
213 case GDISP_ROTATE_0:
214 x = g->p.x;
215 y = g->p.y;
216 break;
217 case GDISP_ROTATE_90:
218 x = g->p.y;
219 y = GDISP_SCREEN_HEIGHT-1 - g->p.x;
220 break;
221 case GDISP_ROTATE_180:
222 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
223 y = GDISP_SCREEN_HEIGHT-1 - g->p.y;
224 break;
225 case GDISP_ROTATE_270:
226 x = GDISP_SCREEN_HEIGHT-1 - g->p.y;
227 y = g->p.x;
228 break;
229 }
230 return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
231 }
232#endif
233
234#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
235 LLDSPEC void gdisp_lld_control(GDisplay *g) {
236 switch(g->p.x) {
237 case GDISP_CONTROL_POWER:
238 if (g->g.Powermode == (powermode_t)g->p.ptr)
239 return;
240 switch((powermode_t)g->p.ptr) {
241 case powerOff:
242 case powerSleep:
243 case powerDeepSleep:
244 acquire_bus(g);
245 write_cmd(g, ST7565_DISPLAY_OFF);
246 release_bus(g);
247 break;
248 case powerOn:
249 acquire_bus(g);
250 write_cmd(g, ST7565_DISPLAY_ON);
251 release_bus(g);
252 break;
253 default:
254 return;
255 }
256 g->g.Powermode = (powermode_t)g->p.ptr;
257 return;
258
259 case GDISP_CONTROL_ORIENTATION:
260 if (g->g.Orientation == (orientation_t)g->p.ptr)
261 return;
262 switch((orientation_t)g->p.ptr) {
263 /* Rotation is handled by the drawing routines */
264 case GDISP_ROTATE_0:
265 case GDISP_ROTATE_180:
266 g->g.Height = GDISP_SCREEN_HEIGHT;
267 g->g.Width = GDISP_SCREEN_WIDTH;
268 break;
269 case GDISP_ROTATE_90:
270 case GDISP_ROTATE_270:
271 g->g.Height = GDISP_SCREEN_WIDTH;
272 g->g.Width = GDISP_SCREEN_HEIGHT;
273 break;
274 default:
275 return;
276 }
277 g->g.Orientation = (orientation_t)g->p.ptr;
278 return;
279
280 case GDISP_CONTROL_CONTRAST:
281 if ((unsigned)g->p.ptr > 100)
282 g->p.ptr = (void *)100;
283 acquire_bus(g);
284 write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F);
285 release_bus(g);
286 g->g.Contrast = (unsigned)g->p.ptr;
287 return;
288 }
289 }
290#endif // GDISP_NEED_CONTROL
291
292#endif // GFX_USE_GDISP
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_config.h b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_config.h
new file mode 100644
index 000000000..48587b9e1
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/gdisp_lld_config.h
@@ -0,0 +1,26 @@
1/*
2 * This file is subject to the terms of the GFX License. If a copy of
3 * the license was not distributed with this file, you can obtain one at:
4 *
5 * http://ugfx.org/license.html
6 */
7
8#ifndef _GDISP_LLD_CONFIG_H
9#define _GDISP_LLD_CONFIG_H
10
11#if GFX_USE_GDISP
12
13/*===========================================================================*/
14/* Driver hardware support. */
15/*===========================================================================*/
16
17#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing
18#define GDISP_HARDWARE_DRAWPIXEL TRUE
19#define GDISP_HARDWARE_PIXELREAD TRUE
20#define GDISP_HARDWARE_CONTROL TRUE
21
22#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO
23
24#endif /* GFX_USE_GDISP */
25
26#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/st7565.h b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/st7565.h
new file mode 100644
index 000000000..48636b33d
--- /dev/null
+++ b/keyboards/infinity_ergodox/drivers/gdisp/st7565ergodox/st7565.h
@@ -0,0 +1,37 @@
1/*
2 * This file is subject to the terms of the GFX License. If a copy of
3 * the license was not distributed with this file, you can obtain one at:
4 *
5 * http://ugfx.org/license.html
6 */
7
8#ifndef _ST7565_H
9#define _ST7565_H
10
11#define ST7565_CONTRAST 0x81
12#define ST7565_ALLON_NORMAL 0xA4
13#define ST7565_ALLON 0xA5
14#define ST7565_POSITIVE_DISPLAY 0xA6
15#define ST7565_INVERT_DISPLAY 0xA7
16#define ST7565_DISPLAY_OFF 0xAE
17#define ST7565_DISPLAY_ON 0xAF
18
19#define ST7565_LCD_BIAS_7 0xA3
20#define ST7565_LCD_BIAS_9 0xA2
21
22#define ST7565_ADC_NORMAL 0xA0
23#define ST7565_ADC_REVERSE 0xA1
24
25#define ST7565_COM_SCAN_INC 0xC0
26#define ST7565_COM_SCAN_DEC 0xC8
27
28#define ST7565_START_LINE 0x40
29#define ST7565_PAGE 0xB0
30#define ST7565_COLUMN_MSB 0x10
31#define ST7565_COLUMN_LSB 0x00
32#define ST7565_RMW 0xE0
33
34#define ST7565_RESISTOR_RATIO 0x20
35#define ST7565_POWER_CONTROL 0x28
36
37#endif /* _ST7565_H */
diff --git a/keyboards/infinity_ergodox/gfxconf.h b/keyboards/infinity_ergodox/gfxconf.h
new file mode 100644
index 000000000..8caa577b7
--- /dev/null
+++ b/keyboards/infinity_ergodox/gfxconf.h
@@ -0,0 +1,331 @@
1/**
2 * This file has a different license to the rest of the uGFX system.
3 * You can copy, modify and distribute this file as you see fit.
4 * You do not need to publish your source modifications to this file.
5 * The only thing you are not permitted to do is to relicense it
6 * under a different license.
7 */
8
9/**
10 * Copy this file into your project directory and rename it as gfxconf.h
11 * Edit your copy to turn on the uGFX features you want to use.
12 * The values below are the defaults.
13 *
14 * Only remove the comments from lines where you want to change the
15 * default value. This allows definitions to be included from
16 * driver makefiles when required and provides the best future
17 * compatibility for your project.
18 *
19 * Please use spaces instead of tabs in this file.
20 */
21
22#ifndef _GFXCONF_H
23#define _GFXCONF_H
24
25
26///////////////////////////////////////////////////////////////////////////
27// GOS - One of these must be defined, preferably in your Makefile //
28///////////////////////////////////////////////////////////////////////////
29//#define GFX_USE_OS_CHIBIOS TRUE
30//#define GFX_USE_OS_FREERTOS FALSE
31// #define GFX_FREERTOS_USE_TRACE FALSE
32//#define GFX_USE_OS_WIN32 FALSE
33//#define GFX_USE_OS_LINUX FALSE
34//#define GFX_USE_OS_OSX FALSE
35//#define GFX_USE_OS_ECOS FALSE
36//#define GFX_USE_OS_RAWRTOS FALSE
37//#define GFX_USE_OS_ARDUINO FALSE
38//#define GFX_USE_OS_KEIL FALSE
39//#define GFX_USE_OS_CMSIS FALSE
40//#define GFX_USE_OS_RAW32 FALSE
41// #define INTERRUPTS_OFF() optional_code
42// #define INTERRUPTS_ON() optional_code
43// These are not defined by default for some reason
44#define GOS_NEED_X_THREADS FALSE
45#define GOS_NEED_X_HEAP FALSE
46
47// Options that (should where relevant) apply to all operating systems
48 #define GFX_NO_INLINE FALSE
49// #define GFX_COMPILER GFX_COMPILER_UNKNOWN
50// #define GFX_CPU GFX_CPU_UNKNOWN
51// #define GFX_OS_HEAP_SIZE 0
52// #define GFX_OS_NO_INIT FALSE
53// #define GFX_OS_INIT_NO_WARNING FALSE
54// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine
55// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine
56// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine
57
58
59///////////////////////////////////////////////////////////////////////////
60// GDISP //
61///////////////////////////////////////////////////////////////////////////
62#define GFX_USE_GDISP TRUE
63
64//#define GDISP_NEED_AUTOFLUSH FALSE
65//#define GDISP_NEED_TIMERFLUSH FALSE
66//#define GDISP_NEED_VALIDATION TRUE
67//#define GDISP_NEED_CLIP TRUE
68#define GDISP_NEED_CIRCLE TRUE
69#define GDISP_NEED_ELLIPSE TRUE
70#define GDISP_NEED_ARC TRUE
71#define GDISP_NEED_ARCSECTORS TRUE
72#define GDISP_NEED_CONVEX_POLYGON TRUE
73//#define GDISP_NEED_SCROLL FALSE
74#define GDISP_NEED_PIXELREAD TRUE
75#define GDISP_NEED_CONTROL TRUE
76//#define GDISP_NEED_QUERY FALSE
77//#define GDISP_NEED_MULTITHREAD FALSE
78//#define GDISP_NEED_STREAMING FALSE
79#define GDISP_NEED_TEXT TRUE
80// #define GDISP_NEED_TEXT_WORDWRAP FALSE
81// #define GDISP_NEED_ANTIALIAS FALSE
82// #define GDISP_NEED_UTF8 FALSE
83 #define GDISP_NEED_TEXT_KERNING TRUE
84// #define GDISP_INCLUDE_FONT_UI1 FALSE
85// #define GDISP_INCLUDE_FONT_UI2 FALSE // The smallest preferred font.
86// #define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
87// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE
88// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE
89// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE
90// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 FALSE
91// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE
92// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE
93 #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 TRUE
94// #define GDISP_INCLUDE_FONT_FIXED_10X20 FALSE
95// #define GDISP_INCLUDE_FONT_FIXED_7X14 FALSE
96 #define GDISP_INCLUDE_FONT_FIXED_5X8 TRUE
97// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE
98// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE
99// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA FALSE
100// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE
101// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE
102// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE
103// #define GDISP_INCLUDE_USER_FONTS FALSE
104
105//#define GDISP_NEED_IMAGE FALSE
106// #define GDISP_NEED_IMAGE_NATIVE FALSE
107// #define GDISP_NEED_IMAGE_GIF FALSE
108// #define GDISP_NEED_IMAGE_BMP FALSE
109// #define GDISP_NEED_IMAGE_BMP_1 FALSE
110// #define GDISP_NEED_IMAGE_BMP_4 FALSE
111// #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE
112// #define GDISP_NEED_IMAGE_BMP_8 FALSE
113// #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE
114// #define GDISP_NEED_IMAGE_BMP_16 FALSE
115// #define GDISP_NEED_IMAGE_BMP_24 FALSE
116// #define GDISP_NEED_IMAGE_BMP_32 FALSE
117// #define GDISP_NEED_IMAGE_JPG FALSE
118// #define GDISP_NEED_IMAGE_PNG FALSE
119// #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
120#ifdef EMULATOR
121#define GDISP_NEED_PIXMAP TRUE
122#endif
123// #define GDISP_NEED_PIXMAP_IMAGE FALSE
124
125//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE // If not defined the native hardware orientation is used.
126//#define GDISP_LINEBUF_SIZE 128
127//#define GDISP_STARTUP_COLOR Black
128#define GDISP_NEED_STARTUP_LOGO FALSE
129
130//#define GDISP_TOTAL_DISPLAYS 2
131
132#ifndef EMULATOR
133#define GDISP_DRIVER_LIST GDISPVMT_ST7565_ERGODOX, GDISPVMT_IS31FL3731C_ERGODOX
134#else
135#define GDISP_DRIVER_LIST GDISPVMT_EMULATOR_LCD_ERGODOX, GDISPVMT_EMULATOR_LED_ERGODOX
136#endif
137
138 #ifdef GDISP_DRIVER_LIST
139 // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability
140 #define GDISP_HARDWARE_STREAM_WRITE FALSE
141 #define GDISP_HARDWARE_STREAM_READ FALSE
142 #define GDISP_HARDWARE_STREAM_POS FALSE
143 #define GDISP_HARDWARE_DRAWPIXEL TRUE
144 #define GDISP_HARDWARE_CLEARS FALSE
145 #define GDISP_HARDWARE_FILLS FALSE
146 #define GDISP_HARDWARE_BITFILLS FALSE
147 #define GDISP_HARDWARE_SCROLL FALSE
148 #define GDISP_HARDWARE_PIXELREAD TRUE
149 #define GDISP_HARDWARE_CONTROL TRUE
150 #define GDISP_HARDWARE_QUERY FALSE
151 #define GDISP_HARDWARE_CLIP FALSE
152
153 #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
154 #endif
155
156// The custom format is not defined for some reason, so define it as error
157// so we don't get compiler warnings
158#define GDISP_PIXELFORMAT_CUSTOM GDISP_PIXELFORMAT_ERROR
159
160#define GDISP_USE_GFXNET FALSE
161// #define GDISP_GFXNET_PORT 13001
162// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE
163// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
164// #define GDISP_GFXNET_UNSAFE_SOCKETS FALSE
165
166
167///////////////////////////////////////////////////////////////////////////
168// GWIN //
169///////////////////////////////////////////////////////////////////////////
170#define GFX_USE_GWIN FALSE
171
172//#define GWIN_NEED_WINDOWMANAGER FALSE
173// #define GWIN_REDRAW_IMMEDIATE FALSE
174// #define GWIN_REDRAW_SINGLEOP FALSE
175// #define GWIN_NEED_FLASHING FALSE
176// #define GWIN_FLASHING_PERIOD 250
177
178//#define GWIN_NEED_CONSOLE FALSE
179// #define GWIN_CONSOLE_USE_HISTORY FALSE
180// #define GWIN_CONSOLE_HISTORY_AVERAGING FALSE
181// #define GWIN_CONSOLE_HISTORY_ATCREATE FALSE
182// #define GWIN_CONSOLE_ESCSEQ FALSE
183// #define GWIN_CONSOLE_USE_BASESTREAM FALSE
184// #define GWIN_CONSOLE_USE_FLOAT FALSE
185//#define GWIN_NEED_GRAPH FALSE
186//#define GWIN_NEED_GL3D FALSE
187
188//#define GWIN_NEED_WIDGET FALSE
189//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
190// #define GWIN_NEED_LABEL FALSE
191// #define GWIN_LABEL_ATTRIBUTE FALSE
192// #define GWIN_NEED_BUTTON FALSE
193// #define GWIN_BUTTON_LAZY_RELEASE FALSE
194// #define GWIN_NEED_SLIDER FALSE
195// #define GWIN_SLIDER_NOSNAP FALSE
196// #define GWIN_SLIDER_DEAD_BAND 5
197// #define GWIN_SLIDER_TOGGLE_INC 20
198// #define GWIN_NEED_CHECKBOX FALSE
199// #define GWIN_NEED_IMAGE FALSE
200// #define GWIN_NEED_IMAGE_ANIMATION FALSE
201// #define GWIN_NEED_RADIO FALSE
202// #define GWIN_NEED_LIST FALSE
203// #define GWIN_NEED_LIST_IMAGES FALSE
204// #define GWIN_NEED_PROGRESSBAR FALSE
205// #define GWIN_PROGRESSBAR_AUTO FALSE
206// #define GWIN_NEED_KEYBOARD FALSE
207// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
208// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
209// #define GWIN_NEED_TEXTEDIT FALSE
210// #define GWIN_FLAT_STYLING FALSE
211// #define GWIN_WIDGET_TAGS FALSE
212
213//#define GWIN_NEED_CONTAINERS FALSE
214// #define GWIN_NEED_CONTAINER FALSE
215// #define GWIN_NEED_FRAME FALSE
216// #define GWIN_NEED_TABSET FALSE
217// #define GWIN_TABSET_TABHEIGHT 18
218
219
220///////////////////////////////////////////////////////////////////////////
221// GEVENT //
222///////////////////////////////////////////////////////////////////////////
223#define GFX_USE_GEVENT TRUE
224
225//#define GEVENT_ASSERT_NO_RESOURCE FALSE
226//#define GEVENT_MAXIMUM_SIZE 32
227//#define GEVENT_MAX_SOURCE_LISTENERS 32
228
229
230///////////////////////////////////////////////////////////////////////////
231// GTIMER //
232///////////////////////////////////////////////////////////////////////////
233#define GFX_USE_GTIMER FALSE
234
235//#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY
236//#define GTIMER_THREAD_WORKAREA_SIZE 2048
237
238
239///////////////////////////////////////////////////////////////////////////
240// GQUEUE //
241///////////////////////////////////////////////////////////////////////////
242#define GFX_USE_GQUEUE FALSE
243
244//#define GQUEUE_NEED_ASYNC FALSE
245//#define GQUEUE_NEED_GSYNC FALSE
246//#define GQUEUE_NEED_FSYNC FALSE
247//#define GQUEUE_NEED_BUFFERS FALSE
248
249///////////////////////////////////////////////////////////////////////////
250// GINPUT //
251///////////////////////////////////////////////////////////////////////////
252#define GFX_USE_GINPUT FALSE
253
254//#define GINPUT_NEED_MOUSE FALSE
255// #define GINPUT_TOUCH_STARTRAW FALSE
256// #define GINPUT_TOUCH_NOTOUCH FALSE
257// #define GINPUT_TOUCH_NOCALIBRATE FALSE
258// #define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE
259// #define GINPUT_MOUSE_POLL_PERIOD 25
260// #define GINPUT_MOUSE_CLICK_TIME 300
261// #define GINPUT_TOUCH_CXTCLICK_TIME 700
262// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD FALSE
263// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE FALSE
264// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32
265//#define GINPUT_NEED_KEYBOARD FALSE
266// #define GINPUT_KEYBOARD_POLL_PERIOD 200
267// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
268// #define GKEYBOARD_LAYOUT_OFF FALSE
269// #define GKEYBOARD_LAYOUT_SCANCODE2_US FALSE
270//#define GINPUT_NEED_TOGGLE FALSE
271//#define GINPUT_NEED_DIAL FALSE
272
273
274///////////////////////////////////////////////////////////////////////////
275// GFILE //
276///////////////////////////////////////////////////////////////////////////
277#define GFX_USE_GFILE FALSE
278
279//#define GFILE_NEED_PRINTG FALSE
280//#define GFILE_NEED_SCANG FALSE
281//#define GFILE_NEED_STRINGS FALSE
282//#define GFILE_NEED_FILELISTS FALSE
283//#define GFILE_NEED_STDIO FALSE
284//#define GFILE_NEED_NOAUTOMOUNT FALSE
285//#define GFILE_NEED_NOAUTOSYNC FALSE
286
287//#define GFILE_NEED_MEMFS FALSE
288//#define GFILE_NEED_ROMFS FALSE
289//#define GFILE_NEED_RAMFS FALSE
290//#define GFILE_NEED_FATFS FALSE
291//#define GFILE_NEED_NATIVEFS FALSE
292//#define GFILE_NEED_CHBIOSFS FALSE
293
294//#define GFILE_ALLOW_FLOATS FALSE
295//#define GFILE_ALLOW_DEVICESPECIFIC FALSE
296//#define GFILE_MAX_GFILES 3
297
298///////////////////////////////////////////////////////////////////////////
299// GADC //
300///////////////////////////////////////////////////////////////////////////
301#define GFX_USE_GADC FALSE
302
303//#define GADC_MAX_LOWSPEED_DEVICES 4
304
305
306///////////////////////////////////////////////////////////////////////////
307// GAUDIO //
308///////////////////////////////////////////////////////////////////////////
309#define GFX_USE_GAUDIO FALSE
310// There seems to be a bug in the ugfx code, the wrong define is used
311// So define it in order to avoid warnings
312#define GFX_USE_GAUDIN GFX_USE_GAUDIO
313// #define GAUDIO_NEED_PLAY FALSE
314// #define GAUDIO_NEED_RECORD FALSE
315
316
317///////////////////////////////////////////////////////////////////////////
318// GMISC //
319///////////////////////////////////////////////////////////////////////////
320#define GFX_USE_GMISC TRUE
321
322//#define GMISC_NEED_ARRAYOPS FALSE
323//#define GMISC_NEED_FASTTRIG FALSE
324//#define GMISC_NEED_FIXEDTRIG FALSE
325//#define GMISC_NEED_INVSQRT FALSE
326// #define GMISC_INVSQRT_MIXED_ENDIAN FALSE
327// #define GMISC_INVSQRT_REAL_SLOW FALSE
328#define GMISC_NEED_MATRIXFLOAT2D TRUE
329#define GMISC_NEED_MATRIXFIXED2D FALSE
330
331#endif /* _GFXCONF_H */
diff --git a/keyboards/infinity_ergodox/infinity_ergodox.c b/keyboards/infinity_ergodox/infinity_ergodox.c
index 85054775e..87ed40fab 100644
--- a/keyboards/infinity_ergodox/infinity_ergodox.c
+++ b/keyboards/infinity_ergodox/infinity_ergodox.c
@@ -2,6 +2,7 @@
2#include "ch.h" 2#include "ch.h"
3#include "hal.h" 3#include "hal.h"
4#include "serial_link/system/serial_link.h" 4#include "serial_link/system/serial_link.h"
5#include "lcd_backlight.h"
5 6
6void init_serial_link_hal(void) { 7void init_serial_link_hal(void) {
7 PORTA->PCR[1] = PORTx_PCRn_PE | PORTx_PCRn_PS | PORTx_PCRn_PFE | PORTx_PCRn_MUX(2); 8 PORTA->PCR[1] = PORTx_PCRn_PE | PORTx_PCRn_PS | PORTx_PCRn_PFE | PORTx_PCRn_MUX(2);
@@ -9,3 +10,67 @@ void init_serial_link_hal(void) {
9 PORTE->PCR[0] = PORTx_PCRn_PE | PORTx_PCRn_PS | PORTx_PCRn_PFE | PORTx_PCRn_MUX(3); 10 PORTE->PCR[0] = PORTx_PCRn_PE | PORTx_PCRn_PS | PORTx_PCRn_PFE | PORTx_PCRn_MUX(3);
10 PORTE->PCR[1] = PORTx_PCRn_DSE | PORTx_PCRn_SRE | PORTx_PCRn_MUX(3); 11 PORTE->PCR[1] = PORTx_PCRn_DSE | PORTx_PCRn_SRE | PORTx_PCRn_MUX(3);
11} 12}
13
14#define RED_PIN 1
15#define GREEN_PIN 2
16#define BLUE_PIN 3
17#define CHANNEL_RED FTM0->CHANNEL[0]
18#define CHANNEL_GREEN FTM0->CHANNEL[1]
19#define CHANNEL_BLUE FTM0->CHANNEL[2]
20
21#define RGB_PORT PORTC
22#define RGB_PORT_GPIO GPIOC
23
24// Base FTM clock selection (72 MHz system clock)
25// @ 0xFFFF period, 72 MHz / (0xFFFF * 2) = Actual period
26// Higher pre-scalar will use the most power (also look the best)
27// Pre-scalar calculations
28// 0 - 72 MHz -> 549 Hz
29// 1 - 36 MHz -> 275 Hz
30// 2 - 18 MHz -> 137 Hz
31// 3 - 9 MHz -> 69 Hz (Slightly visible flicker)
32// 4 - 4 500 kHz -> 34 Hz (Visible flickering)
33// 5 - 2 250 kHz -> 17 Hz
34// 6 - 1 125 kHz -> 9 Hz
35// 7 - 562 500 Hz -> 4 Hz
36// Using a higher pre-scalar without flicker is possible but FTM0_MOD will need to be reduced
37// Which will reduce the brightness range
38#define PRESCALAR_DEFINE 0
39
40void lcd_backlight_hal_init(void) {
41 // Setup Backlight
42 SIM->SCGC6 |= SIM_SCGC6_FTM0;
43 FTM0->CNT = 0; // Reset counter
44
45 // PWM Period
46 // 16-bit maximum
47 FTM0->MOD = 0xFFFF;
48
49 // Set FTM to PWM output - Edge Aligned, Low-true pulses
50#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0)
51 CHANNEL_RED.CnSC = CNSC_MODE;
52 CHANNEL_GREEN.CnSC = CNSC_MODE;
53 CHANNEL_BLUE.CnSC = CNSC_MODE;
54
55 // System clock, /w prescalar setting
56 FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE);
57
58 CHANNEL_RED.CnV = 0;
59 CHANNEL_GREEN.CnV = 0;
60 CHANNEL_BLUE.CnV = 0;
61
62 RGB_PORT_GPIO->PDDR |= (1 << RED_PIN);
63 RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN);
64 RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN);
65
66#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4)
67 RGB_PORT->PCR[RED_PIN] = RGB_MODE;
68 RGB_PORT->PCR[GREEN_PIN] = RGB_MODE;
69 RGB_PORT->PCR[BLUE_PIN] = RGB_MODE;
70}
71
72void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) {
73 CHANNEL_RED.CnV = r;
74 CHANNEL_GREEN.CnV = g;
75 CHANNEL_BLUE.CnV = b;
76}
diff --git a/keyboards/infinity_ergodox/keymaps/default/visualizer.c b/keyboards/infinity_ergodox/keymaps/default/visualizer.c
new file mode 100644
index 000000000..c0d335ce6
--- /dev/null
+++ b/keyboards/infinity_ergodox/keymaps/default/visualizer.c
@@ -0,0 +1,168 @@
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 "led_test.h"
31
32static const char* welcome_text[] = {"TMK", "Infinity Ergodox"};
33
34// Just an example how to write custom keyframe functions, we could have moved
35// all this into the init function
36bool display_welcome(keyframe_animation_t* animation, visualizer_state_t* state) {
37 (void)animation;
38 // Read the uGFX documentation for information how to use the displays
39 // http://wiki.ugfx.org/index.php/Main_Page
40 gdispClear(White);
41 // You can use static variables for things that can't be found in the animation
42 // or state structs
43 gdispDrawString(0, 3, welcome_text[0], state->font_dejavusansbold12, Black);
44 gdispDrawString(0, 15, welcome_text[1], state->font_dejavusansbold12, Black);
45 // Always remember to flush the display
46 gdispFlush();
47 // you could set the backlight color as well, but we won't do it here, since
48 // it's part of the following animation
49 // lcd_backlight_color(hue, saturation, intensity);
50 // We don't need constant updates, just drawing the screen once is enough
51 return false;
52}
53
54// Feel free to modify the animations below, or even add new ones if needed
55
56// Don't worry, if the startup animation is long, you can use the keyboard like normal
57// during that time
58static keyframe_animation_t startup_animation = {
59 .num_frames = 4,
60 .loop = false,
61 .frame_lengths = {0, gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(5000), 0},
62 .frame_functions = {
63 display_welcome,
64 keyframe_animate_backlight_color,
65 keyframe_no_operation,
66 enable_visualization
67 },
68};
69
70// The color animation animates the LCD color when you change layers
71static keyframe_animation_t color_animation = {
72 .num_frames = 2,
73 .loop = false,
74 // Note that there's a 200 ms no-operation frame,
75 // this prevents the color from changing when activating the layer
76 // momentarily
77 .frame_lengths = {gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(500)},
78 .frame_functions = {keyframe_no_operation, keyframe_animate_backlight_color},
79};
80
81// The LCD animation alternates between the layer name display and a
82// bitmap that displays all active layers
83static keyframe_animation_t lcd_animation = {
84 .num_frames = 2,
85 .loop = true,
86 .frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)},
87 .frame_functions = {keyframe_display_layer_text, keyframe_display_layer_bitmap},
88};
89
90static keyframe_animation_t suspend_animation = {
91 .num_frames = 3,
92 .loop = false,
93 .frame_lengths = {0, gfxMillisecondsToTicks(1000), 0},
94 .frame_functions = {
95 keyframe_display_layer_text,
96 keyframe_animate_backlight_color,
97 keyframe_disable_lcd_and_backlight,
98 },
99};
100
101static keyframe_animation_t resume_animation = {
102 .num_frames = 5,
103 .loop = false,
104 .frame_lengths = {0, 0, gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(5000), 0},
105 .frame_functions = {
106 keyframe_enable_lcd_and_backlight,
107 display_welcome,
108 keyframe_animate_backlight_color,
109 keyframe_no_operation,
110 enable_visualization,
111 },
112};
113
114void initialize_user_visualizer(visualizer_state_t* state) {
115 // The brightness will be dynamically adjustable in the future
116 // But for now, change it here.
117 lcd_backlight_brightness(0x50);
118 state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0xFF);
119 state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF);
120 start_keyframe_animation(&startup_animation);
121 start_keyframe_animation(&led_test_animation);
122}
123
124void update_user_visualizer_state(visualizer_state_t* state) {
125 // Add more tests, change the colors and layer texts here
126 // Usually you want to check the high bits (higher layers first)
127 // because that's the order layers are processed for keypresses
128 // You can for check for example:
129 // state->status.layer
130 // state->status.default_layer
131 // state->status.leds (see led.h for available statuses)
132 if (state->status.layer & 0x8) {
133 state->target_lcd_color = LCD_COLOR(0xC0, 0xB0, 0xFF);
134 state->layer_text = "Numpad";
135 }
136 else if (state->status.layer & 0x4) {
137 state->target_lcd_color = LCD_COLOR(0, 0xB0, 0xFF);
138 state->layer_text = "KBD functions";
139 }
140 else if (state->status.layer & 0x2) {
141 state->target_lcd_color = LCD_COLOR(0x80, 0xB0, 0xFF);
142 state->layer_text = "Function keys";
143 }
144 else {
145 state->target_lcd_color = LCD_COLOR(0x40, 0xB0, 0xFF);
146 state->layer_text = "Default";
147 }
148 // You can also stop existing animations, and start your custom ones here
149 // remember that you should normally have only one animation for the LCD
150 // and one for the background. But you can also combine them if you want.
151 start_keyframe_animation(&lcd_animation);
152 start_keyframe_animation(&color_animation);
153}
154
155void user_visualizer_suspend(visualizer_state_t* state) {
156 state->layer_text = "Suspending...";
157 uint8_t hue = LCD_HUE(state->current_lcd_color);
158 uint8_t sat = LCD_SAT(state->current_lcd_color);
159 state->target_lcd_color = LCD_COLOR(hue, sat, 0);
160 start_keyframe_animation(&suspend_animation);
161}
162
163void user_visualizer_resume(visualizer_state_t* state) {
164 state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0x00);
165 state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF);
166 start_keyframe_animation(&resume_animation);
167 start_keyframe_animation(&led_test_animation);
168}
diff --git a/lib/ugfx b/lib/ugfx
new file mode 160000
Subproject 13e084ae6231857cd0d472c529f34be07d93c08
diff --git a/quantum/visualizer/led_test.c b/quantum/visualizer/led_test.c
index c2ea30b55..a9abace8d 100644
--- a/quantum/visualizer/led_test.c
+++ b/quantum/visualizer/led_test.c
@@ -89,8 +89,8 @@ static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS];
89static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; 89static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS];
90 90
91static uint8_t compute_gradient_color(float t, float index, float num) { 91static uint8_t compute_gradient_color(float t, float index, float num) {
92 const float two_pi = 2.0f * PI; 92 const float two_pi = M_2_PI;
93 float normalized_index = (1.0f - index / (num - 1)) * two_pi; 93 float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi;
94 float x = t * two_pi + normalized_index; 94 float x = t * two_pi + normalized_index;
95 float v = 0.5 * (cosf(x) + 1.0f); 95 float v = 0.5 * (cosf(x) + 1.0f);
96 return (uint8_t)(255.0f * v); 96 return (uint8_t)(255.0f * v);
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c
index c24073405..54f6faaa4 100644
--- a/quantum/visualizer/visualizer.c
+++ b/quantum/visualizer/visualizer.c
@@ -29,9 +29,7 @@ SOFTWARE.
29#include "ch.h" 29#include "ch.h"
30#endif 30#endif
31 31
32#ifdef LCD_ENABLE
33#include "gfx.h" 32#include "gfx.h"
34#endif
35 33
36#ifdef LCD_BACKLIGHT_ENABLE 34#ifdef LCD_BACKLIGHT_ENABLE
37#include "lcd_backlight.h" 35#include "lcd_backlight.h"
@@ -45,7 +43,7 @@ SOFTWARE.
45#include "nodebug.h" 43#include "nodebug.h"
46#endif 44#endif
47 45
48#ifdef USE_SERIAL_LINK 46#ifdef SERIAL_LINK_ENABLE
49#include "serial_link/protocol/transport.h" 47#include "serial_link/protocol/transport.h"
50#include "serial_link/system/serial_link.h" 48#include "serial_link/system/serial_link.h"
51#endif 49#endif
@@ -75,7 +73,7 @@ static bool visualizer_enabled = false;
75#define MAX_SIMULTANEOUS_ANIMATIONS 4 73#define MAX_SIMULTANEOUS_ANIMATIONS 4
76static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; 74static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {};
77 75
78#ifdef USE_SERIAL_LINK 76#ifdef SERIAL_LINK_ENABLE
79MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t); 77MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t);
80 78
81static remote_object_t* remote_objects[] = { 79static remote_object_t* remote_objects[] = {
@@ -458,15 +456,13 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
458} 456}
459 457
460void visualizer_init(void) { 458void visualizer_init(void) {
461#ifdef LCD_ENABLE
462 gfxInit(); 459 gfxInit();
463#endif
464 460
465#ifdef LCD_BACKLIGHT_ENABLE 461#ifdef LCD_BACKLIGHT_ENABLE
466 lcd_backlight_init(); 462 lcd_backlight_init();
467#endif 463#endif
468 464
469#ifdef USE_SERIAL_LINK 465#ifdef SERIAL_LINK_ENABLE
470 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); 466 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) );
471#endif 467#endif
472 468
@@ -490,7 +486,7 @@ void update_status(bool changed) {
490 geventSendEvent(listener); 486 geventSendEvent(listener);
491 } 487 }
492 } 488 }
493#ifdef USE_SERIAL_LINK 489#ifdef SERIAL_LINK_ENABLE
494 static systime_t last_update = 0; 490 static systime_t last_update = 0;
495 systime_t current_update = chVTGetSystemTimeX(); 491 systime_t current_update = chVTGetSystemTimeX();
496 systime_t delta = current_update - last_update; 492 systime_t delta = current_update - last_update;
@@ -510,7 +506,7 @@ void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) {
510 // Alternatively a mutex could be used instead of the volatile variables 506 // Alternatively a mutex could be used instead of the volatile variables
511 507
512 bool changed = false; 508 bool changed = false;
513#ifdef USE_SERIAL_LINK 509#ifdef SERIAL_LINK_ENABLE
514 if (is_serial_link_connected ()) { 510 if (is_serial_link_connected ()) {
515 visualizer_keyboard_status_t* new_status = read_current_status(); 511 visualizer_keyboard_status_t* new_status = read_current_status();
516 if (new_status) { 512 if (new_status) {
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h
index 45cfa9aa9..53e250725 100644
--- a/quantum/visualizer/visualizer.h
+++ b/quantum/visualizer/visualizer.h
@@ -28,9 +28,7 @@ SOFTWARE.
28#include <stdint.h> 28#include <stdint.h>
29#include <stdbool.h> 29#include <stdbool.h>
30 30
31#ifdef LCD_ENABLE
32#include "gfx.h" 31#include "gfx.h"
33#endif
34 32
35#ifdef LCD_BACKLIGHT_ENABLE 33#ifdef LCD_BACKLIGHT_ENABLE
36#include "lcd_backlight.h" 34#include "lcd_backlight.h"
diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk
index 56525ffd9..2f4a41d66 100644
--- a/quantum/visualizer/visualizer.mk
+++ b/quantum/visualizer/visualizer.mk
@@ -20,41 +20,41 @@
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE. 21# SOFTWARE.
22 22
23GFXLIB = $(VISUALIZER_DIR)/ugfx
24SRC += $(VISUALIZER_DIR)/visualizer.c 23SRC += $(VISUALIZER_DIR)/visualizer.c
25UINCDIR += $(GFXINC) $(VISUALIZER_DIR) 24EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR)
25GFXLIB = $(LIB_PATH)/ugfx
26VPATH += $(VISUALIZER_PATH)
27
28OPT_DEFS += -DVISUALIZER_ENABLE
26 29
27ifdef LCD_ENABLE 30ifdef LCD_ENABLE
28UDEFS += -DLCD_ENABLE 31OPT_DEFS += -DLCD_ENABLE
29ULIBS += -lm 32ULIBS += -lm
30USE_UGFX = yes
31endif 33endif
32 34
33ifdef LCD_BACKLIGHT_ENABLE 35ifdef LCD_BACKLIGHT_ENABLE
34SRC += $(VISUALIZER_DIR)/lcd_backlight.c 36SRC += $(VISUALIZER_DIR)/lcd_backlight.c
35ifndef EMULATOR 37OPT_DEFS += -DLCD_BACKLIGHT_ENABLE
36SRC += lcd_backlight_hal.c
37endif
38UDEFS += -DLCD_BACKLIGHT_ENABLE
39endif 38endif
40 39
41ifdef LED_ENABLE 40ifdef LED_ENABLE
42SRC += $(VISUALIZER_DIR)/led_test.c 41SRC += $(VISUALIZER_DIR)/led_test.c
43UDEFS += -DLED_ENABLE 42OPT_DEFS += -DLED_ENABLE
44USE_UGFX = yes
45endif 43endif
46 44
47ifdef USE_UGFX
48include $(GFXLIB)/gfx.mk 45include $(GFXLIB)/gfx.mk
49SRC += $(GFXSRC) 46SRC += $(patsubst $(TOP_DIR)/%,%,$(GFXSRC))
50UDEFS += $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) 47OPT_DEFS += $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS)))
51ULIBS += $(patsubst %,-l%,$(patsubst -l%,%,$(GFXLIBS)))
52endif
53 48
54ifndef VISUALIZER_USER 49ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","")
55VISUALIZER_USER = visualizer_user.c 50 SRC += keyboards/$(KEYBOARD)/keymaps/$(KEYMAP)/visualizer.c
51else
52 ifeq ("$(wildcard $(SUBPROJECT_PATH)/keymaps/$(KEYMAP)/visualizer.c)","")
53$(error "$(KEYMAP_PATH)/visualizer.c" does not exist)
54 else
55 SRC += keyboards/$(KEYBOARD)/$(SUBPROJECT)/keymaps/$(KEYMAP)/visualizer.c
56 endif
56endif 57endif
57SRC += $(VISUALIZER_USER)
58 58
59ifdef EMULATOR 59ifdef EMULATOR
60UINCDIR += $(TMK_DIR)/common 60UINCDIR += $(TMK_DIR)/common
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index 3a1262a9f..c46a701b3 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
29#include "sendchar.h" 29#include "sendchar.h"
30#include "eeconfig.h" 30#include "eeconfig.h"
31#include "backlight.h" 31#include "backlight.h"
32#include "action_layer.h"
32#ifdef BOOTMAGIC_ENABLE 33#ifdef BOOTMAGIC_ENABLE
33# include "bootmagic.h" 34# include "bootmagic.h"
34#else 35#else
@@ -52,6 +53,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
52#ifdef SERIAL_LINK_ENABLE 53#ifdef SERIAL_LINK_ENABLE
53# include "serial_link/system/serial_link.h" 54# include "serial_link/system/serial_link.h"
54#endif 55#endif
56#ifdef VISUALIZER_ENABLE
57# include "visualizer/visualizer.h"
58#endif
55 59
56#ifdef MATRIX_HAS_GHOST 60#ifdef MATRIX_HAS_GHOST
57static bool has_ghost_in_row(uint8_t row) 61static bool has_ghost_in_row(uint8_t row)
@@ -181,6 +185,10 @@ MATRIX_LOOP_END:
181 serial_link_update(); 185 serial_link_update();
182#endif 186#endif
183 187
188#ifdef VISUALIZER_ENABLE
189 visualizer_update(default_layer_state, layer_state, host_keyboard_leds());
190#endif
191
184 // update LED 192 // update LED
185 if (led_status != host_keyboard_leds()) { 193 if (led_status != host_keyboard_leds()) {
186 led_status = host_keyboard_leds(); 194 led_status = host_keyboard_leds();
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
index aeb11752f..b0eb9aef8 100644
--- a/tmk_core/protocol/chibios/main.c
+++ b/tmk_core/protocol/chibios/main.c
@@ -38,6 +38,9 @@
38#ifdef SERIAL_LINK_ENABLE 38#ifdef SERIAL_LINK_ENABLE
39#include "serial_link/system/serial_link.h" 39#include "serial_link/system/serial_link.h"
40#endif 40#endif
41#ifdef VISUALIZER_ENABLE
42#include "visualizer/visualizer.h"
43#endif
41#include "suspend.h" 44#include "suspend.h"
42 45
43 46
@@ -105,6 +108,11 @@ int main(void) {
105 init_serial_link(); 108 init_serial_link();
106#endif 109#endif
107 110
111#ifdef VISUALIZER_ENABLE
112 visualizer_init();
113#endif
114
115
108 host_driver_t* driver = NULL; 116 host_driver_t* driver = NULL;
109 117
110 /* Wait until the USB or serial link is active */ 118 /* Wait until the USB or serial link is active */
@@ -147,6 +155,9 @@ int main(void) {
147 155
148 if(USB_DRIVER.state == USB_SUSPENDED) { 156 if(USB_DRIVER.state == USB_SUSPENDED) {
149 print("[s]"); 157 print("[s]");
158#ifdef VISUALIZER_ENABLE
159 visualizer_suspend();
160#endif
150 while(USB_DRIVER.state == USB_SUSPENDED) { 161 while(USB_DRIVER.state == USB_SUSPENDED) {
151 /* Do this in the suspended state */ 162 /* Do this in the suspended state */
152#ifdef SERIAL_LINK_ENABLE 163#ifdef SERIAL_LINK_ENABLE
@@ -164,6 +175,10 @@ int main(void) {
164#ifdef MOUSEKEY_ENABLE 175#ifdef MOUSEKEY_ENABLE
165 mousekey_send(); 176 mousekey_send();
166#endif /* MOUSEKEY_ENABLE */ 177#endif /* MOUSEKEY_ENABLE */
178
179#ifdef VISUALIZER_ENABLE
180 visualizer_resume();
181#endif
167 } 182 }
168 183
169 keyboard_task(); 184 keyboard_task();