Skip to content

Commit 9004ac3

Browse files
committed
Update my keymap for new ST7565 driver.
More or less copied my visualizer.
1 parent 2530823 commit 9004ac3

File tree

8 files changed

+341
-25
lines changed

8 files changed

+341
-25
lines changed

layouts/community/ergodox/firetech/bongocat.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121

2222
#define BONGOCAT_LINEWIDTH 56 // ceil(BONGOCAT_WIDTH / 8.0) * 8
2323

24-
const uint8_t bongocat[][BONGOCAT_LINEWIDTH*BONGOCAT_HEIGHT/8] = {
24+
#define BONGOCAT_LENGTH BONGOCAT_LINEWIDTH*BONGOCAT_HEIGHT/8
25+
26+
const uint8_t PROGMEM bongocat[][BONGOCAT_LENGTH] = {
2527
// .o.
2628
{
2729
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff,

layouts/community/ergodox/firetech/config.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@
66

77
#define PERMISSIVE_HOLD
88

9-
#ifdef KEYBOARD_ergodox_infinity
10-
# undef BACKLIGHT_LEVELS
11-
# define BACKLIGHT_LEVELS 5
12-
# undef LED_MATRIX_VAL_STEP
13-
# define LED_MATRIX_VAL_STEP 51
14-
15-
# define EE_HANDS
9+
#undef BACKLIGHT_LEVELS
10+
#define BACKLIGHT_LEVELS 5
11+
#undef LED_MATRIX_VAL_STEP
12+
#define LED_MATRIX_VAL_STEP 51
1613

14+
#ifdef SPLIT_KEYBOARD
1715
# define SPLIT_WPM_ENABLE
18-
# define SPLIT_TRANSACTION_IDS_USER MAX_WPM
16+
# define SPLIT_TRANSACTION_IDS_USER FT_MAX_WPM, FT_DISPLAY_STATE
1917
# define SPLIT_TRANSPORT_MIRROR
2018
# define LED_MATRIX_KEYREACTIVE_ENABLED
2119
#endif
2220

21+
#ifdef ST7565_ENABLE
22+
# define ST7565_TIMEOUT 0
23+
#endif
24+
25+
#ifdef KEYBOARD_ergodox_infinity
26+
# define EE_HANDS
27+
#endif
28+
2329
#ifdef KEYBOARD_ergodox_ez
2430
# define QMK_KEYS_PER_SCAN 4
2531
#endif
32+
33+
#define DEBUG_MATRIX_SCAN_RATE

layouts/community/ergodox/firetech/keymap_extra.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515
*/
1616

1717
#include QMK_KEYBOARD_H
18+
#include <string.h>
19+
#include <stdio.h>
20+
1821
#include "wpm.h"
1922
#include "keymap_extra.h"
20-
#include <stdio.h>
23+
#ifdef ST7565_ENABLE
24+
# include "keymap_st7565.h"
25+
#endif
2126

2227
#define WPM_BUF_SIZE 4
2328

@@ -29,35 +34,58 @@ enum custom_keycodes {
2934

3035
static uint8_t max_wpm = 0;
3136

32-
#if defined(SPLIT_KEYBOARD) && defined(WPM_ENABLE)
37+
#if defined(SPLIT_KEYBOARD) && (defined(WPM_ENABLE) || defined(ST7565_ENABLE))
3338
# include "transactions.h"
3439

3540
# ifndef FORCED_SYNC_THROTTLE_MS
3641
# define FORCED_SYNC_THROTTLE_MS 100
3742
# endif
3843

44+
# ifdef WPM_ENABLE
3945
void max_wpm_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
4046
set_max_wpm(*((uint8_t *)in_data));
4147
}
4248

4349
static bool max_wpm_changed = false;
50+
# endif
51+
52+
# ifdef ST7565_ENABLE
53+
void display_state_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
54+
set_ft_display_state((ft_display_state_t *)in_data);
55+
}
56+
# endif
4457

4558
void housekeeping_task_user(void) {
4659
if (is_keyboard_master()) {
60+
# ifdef WPM_ENABLE
4761
static uint16_t last_max_wpm_update = 0;
4862
if (max_wpm_changed || timer_elapsed(last_max_wpm_update) > FORCED_SYNC_THROTTLE_MS) {
49-
if (transaction_rpc_send(MAX_WPM, sizeof(max_wpm), &max_wpm)) {
63+
if (transaction_rpc_send(FT_MAX_WPM, sizeof(max_wpm), &max_wpm)) {
5064
max_wpm_changed = false;
5165
last_max_wpm_update = timer_read();
5266
}
5367
}
68+
# endif
69+
# ifdef ST7565_ENABLE
70+
static uint16_t last_display_state_update = 0;
71+
static ft_display_state_t last_display_state;
72+
if (!same_ft_display_state(&last_display_state, &ft_display_state) || timer_elapsed(last_display_state_update) > FORCED_SYNC_THROTTLE_MS) {
73+
if (transaction_rpc_send(FT_DISPLAY_STATE, sizeof(ft_display_state), &ft_display_state)) {
74+
memcpy(&last_display_state, &ft_display_state, sizeof(last_display_state));
75+
last_display_state_update = timer_read();
76+
}
77+
}
78+
# endif
5479
}
5580
}
5681
#endif
5782

5883
void keyboard_post_init_user(void) {
5984
#ifdef SPLIT_KEYBOARD
60-
transaction_register_rpc(MAX_WPM, max_wpm_slave_handler);
85+
transaction_register_rpc(FT_MAX_WPM, max_wpm_slave_handler);
86+
# ifdef ST7565_ENABLE
87+
transaction_register_rpc(FT_DISPLAY_STATE, display_state_slave_handler);
88+
# endif
6189
#endif
6290
}
6391

layouts/community/ergodox/firetech/keymap_extra.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,8 @@
1616

1717
#pragma once
1818

19+
#define SWAP_LAYER 1
20+
#define FN_LAYER 2
21+
1922
uint8_t get_max_wpm(void);
2023
void set_max_wpm(uint8_t);
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
#include QMK_KEYBOARD_H
2+
#include <math.h>
3+
#include <string.h>
4+
5+
#include "keymap_st7565.h"
6+
#include "keymap_extra.h"
7+
#include "bongocat.h"
8+
9+
#define STAT_BUF_SIZE 10
10+
11+
#define WPM_ANIM_START 20 // Animation idle below this WPM value
12+
#define WPM_TO_FRAME_TIME(wpm) (2565 - 537 * log(wpm)) // Formula to convert WPM to frame time
13+
14+
ft_display_state_t ft_display_state = {
15+
.is_on = true,
16+
.leds = 0xFF,
17+
.layer = 0xFFFFFFFF,
18+
.swap_displays = false,
19+
};
20+
static bool clear_display = true;
21+
22+
void set_ft_display_state(ft_display_state_t* new_state) {
23+
if (!same_ft_display_state(&ft_display_state, new_state)) {
24+
memcpy(&ft_display_state, new_state, sizeof(ft_display_state));
25+
if (ft_display_state.is_on != st7565_is_on()) {
26+
if (ft_display_state.is_on) {
27+
st7565_on();
28+
} else {
29+
st7565_off();
30+
}
31+
}
32+
clear_display = true;
33+
}
34+
}
35+
36+
bool same_ft_display_state(ft_display_state_t *a, ft_display_state_t *b) {
37+
if (a->is_on == b->is_on &&
38+
a->leds == b->leds &&
39+
a->layer == b->layer &&
40+
a->layer == b->layer &&
41+
a->swap_displays == b->swap_displays) {
42+
return true;
43+
}
44+
return false;
45+
}
46+
47+
/* LCD backlight code copied from quantum/visualizer/lcd_backlight.c */
48+
static uint8_t current_hue = 0;
49+
static uint8_t current_saturation = 0;
50+
static uint8_t current_intensity = 0;
51+
static uint8_t current_brightness = 255;
52+
53+
// This code is based on Brian Neltner's blogpost and example code
54+
// "Why every LED light should be using HSI colorspace".
55+
// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi
56+
static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) {
57+
unsigned int r, g, b;
58+
h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees
59+
h = 3.14159f * h / 180.0f; // Convert to radians.
60+
s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1]
61+
i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f;
62+
63+
// Math! Thanks in part to Kyle Miller.
64+
if (h < 2.09439f) {
65+
r = 65535.0f * i / 3.0f * (1.0f + s * cos(h) / cosf(1.047196667f - h));
66+
g = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cos(1.047196667f - h)));
67+
b = 65535.0f * i / 3.0f * (1.0f - s);
68+
} else if (h < 4.188787) {
69+
h = h - 2.09439;
70+
g = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
71+
b = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
72+
r = 65535.0f * i / 3.0f * (1.0f - s);
73+
} else {
74+
h = h - 4.188787;
75+
b = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
76+
r = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
77+
g = 65535.0f * i / 3.0f * (1.0f - s);
78+
}
79+
*r_out = r > 65535 ? 65535 : r;
80+
*g_out = g > 65535 ? 65535 : g;
81+
*b_out = b > 65535 ? 65535 : b;
82+
}
83+
84+
static void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) {
85+
uint16_t r, g, b;
86+
float hue_f = 360.0f * (float)hue / 255.0f;
87+
float saturation_f = (float)saturation / 255.0f;
88+
float intensity_f = (float)intensity / 255.0f;
89+
intensity_f *= (float)current_brightness / 255.0f;
90+
hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b);
91+
current_hue = hue;
92+
current_saturation = saturation;
93+
current_intensity = intensity;
94+
ergodox_infinity_lcd_color(r, g, b);
95+
}
96+
97+
static void lcd_backlight_brightness(uint8_t b) {
98+
current_brightness = b;
99+
lcd_backlight_color(current_hue, current_saturation, current_intensity);
100+
}
101+
/* End of copied LCD backlight code */
102+
103+
static uint8_t prev_brightness = 0;
104+
105+
void st7565_on_user(void) {
106+
ft_display_state.is_on = true;
107+
lcd_backlight_brightness(prev_brightness);
108+
}
109+
110+
void st7565_off_user(void) {
111+
ft_display_state.is_on = false;
112+
prev_brightness = current_brightness;
113+
lcd_backlight_brightness(0);
114+
}
115+
116+
void set_hand_swap(bool do_swap) {
117+
ft_display_state.swap_displays = do_swap;
118+
clear_display = true;
119+
}
120+
121+
static inline void write_led_state(uint8_t *row, uint8_t *col, uint8_t led, const char *text_P) {
122+
if (ft_display_state.leds & (1u << led)) {
123+
const size_t length = strlen_P(text_P);
124+
if (*col + length > st7565_max_chars()) {
125+
st7565_advance_page(true);
126+
st7565_write_P(PSTR(" "), false);
127+
*col = 2;
128+
*row += 1;
129+
}
130+
st7565_write_P(text_P, false);
131+
st7565_write_char(' ', false);
132+
*col += length + 1;
133+
}
134+
}
135+
136+
void draw_right(const char *layer_text_P) {
137+
st7565_write_ln_P(layer_text_P, false);
138+
if (strlen_P(layer_text_P) < st7565_max_chars()) {
139+
st7565_advance_page(true);
140+
}
141+
142+
st7565_write_char(0x2A, false);
143+
st7565_write_char(' ', false);
144+
uint8_t row = 2;
145+
uint8_t col = 2;
146+
write_led_state(&row, &col, USB_LED_NUM_LOCK, PSTR("Num"));
147+
write_led_state(&row, &col, USB_LED_CAPS_LOCK, PSTR("Caps"));
148+
write_led_state(&row, &col, USB_LED_SCROLL_LOCK, PSTR("Scroll"));
149+
write_led_state(&row, &col, USB_LED_COMPOSE, PSTR("Compose"));
150+
write_led_state(&row, &col, USB_LED_KANA, PSTR("Kana"));
151+
while (row++ <= 3) {
152+
st7565_advance_page(true);
153+
}
154+
}
155+
156+
void draw_left(void) {
157+
char stat_buf[STAT_BUF_SIZE];
158+
159+
const uint8_t* wpm_frame = bongocat[0];
160+
#ifdef WPM_ENABLE
161+
uint8_t wpm = get_current_wpm();
162+
163+
st7565_advance_page(true);
164+
st7565_advance_page(true);
165+
st7565_write_P(PSTR("WPM: "), false);
166+
snprintf(stat_buf, STAT_BUF_SIZE, "%3u", wpm);
167+
st7565_write_ln(stat_buf, false);
168+
169+
st7565_write_P(PSTR("Max: "), false);
170+
snprintf(stat_buf, STAT_BUF_SIZE, "%3u", get_max_wpm());
171+
st7565_write_ln(stat_buf, false);
172+
173+
static uint16_t wpm_anim_timer = 0;
174+
static uint8_t wpm_anim_at_frame = 1;
175+
if (wpm >= WPM_ANIM_START) {
176+
wpm_frame = bongocat[wpm_anim_at_frame];
177+
178+
if (timer_elapsed(wpm_anim_timer) >= WPM_TO_FRAME_TIME(wpm)) {
179+
wpm_anim_at_frame = 3 - wpm_anim_at_frame;
180+
wpm_anim_timer = timer_read();
181+
}
182+
}
183+
#endif
184+
185+
debug_enable = true;
186+
uint8_t x = ST7565_DISPLAY_WIDTH - BONGOCAT_WIDTH;
187+
uint8_t y = 0;
188+
for (uint8_t byte = 0; byte < BONGOCAT_LENGTH; byte++) {
189+
uint8_t pixels = pgm_read_byte(wpm_frame + byte);
190+
for (uint8_t mask = (1u << 7); mask > 0; mask >>= 1) {
191+
st7565_write_pixel(x, y, (pixels & mask) == 0);
192+
if (++x > ST7565_DISPLAY_WIDTH) {
193+
x = ST7565_DISPLAY_WIDTH - BONGOCAT_WIDTH;
194+
y++;
195+
break;
196+
}
197+
}
198+
}
199+
200+
#ifdef LED_MATRIX_ENABLE
201+
if (ft_display_state.layer & (1 << FN_LAYER)) {
202+
st7565_set_cursor(0, 0);
203+
uint8_t brightness = led_matrix_get_val();
204+
uint8_t backlight_level = 0;
205+
if (led_matrix_is_enabled()) {
206+
backlight_level = brightness * 100.0 / UINT8_MAX;
207+
}
208+
st7565_write_P(PSTR("Backlight: "), false);
209+
snprintf(stat_buf, STAT_BUF_SIZE, "%3u%%", backlight_level);
210+
st7565_write(stat_buf, false);
211+
}
212+
#endif
213+
}
214+
215+
void st7565_task_user(void) {
216+
if (is_keyboard_master()) {
217+
ft_display_state.is_on = st7565_is_on();
218+
ft_display_state.leds = host_keyboard_leds();
219+
ft_display_state.layer = layer_state;
220+
}
221+
222+
if (ft_display_state.is_on) {
223+
#ifdef LED_MATRIX_ENABLE
224+
lcd_backlight_brightness(led_matrix_get_val());
225+
#endif
226+
227+
const char *layer_text_P;
228+
if (ft_display_state.layer & (1 << FN_LAYER)) {
229+
lcd_backlight_color(170, 255, 255);
230+
if (ft_display_state.layer & (1 << SWAP_LAYER)) {
231+
layer_text_P = PSTR("Fn Swap On Space");
232+
} else {
233+
layer_text_P = PSTR("Fn");
234+
}
235+
} else if (ft_display_state.layer & (1 << SWAP_LAYER)) {
236+
lcd_backlight_color(128, 255, 255);
237+
layer_text_P = PSTR("Swap On Space");
238+
} else {
239+
lcd_backlight_color(0, 0, 255);
240+
layer_text_P = PSTR("Default");
241+
}
242+
243+
bool is_left = is_keyboard_left();
244+
if (ft_display_state.swap_displays) { is_left = !is_left; }
245+
246+
if (clear_display) {
247+
st7565_clear();
248+
clear_display = false;
249+
}
250+
251+
if (is_left) {
252+
draw_left();
253+
} else {
254+
draw_right(layer_text_P);
255+
}
256+
}
257+
}

0 commit comments

Comments
 (0)