Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern mode key bindings #194

Merged
merged 15 commits into from Apr 9, 2020
@@ -9,6 +9,11 @@
- **NEW**: `LSH` and `RSH` shift the opposite direction when passed a negative shift amount
- **NEW**: new op: `SGN` (sign of argument)
- **NEW**: new kria remote op: `KR.DUR`
- **NEW**: new Tracker mode keybinding `alt-[ ]` semitone up, down
- **NEW**: new Tracker mode keybinding `ctrl-[ ]` fifth up, down
- **NEW**: new Tracker mode keybinding `shift-[ ]` octave up, down
- **NEW**: new Tracker mode keybinding `alt-<0-9>` `<0-9>` semitones up (0=10, 1=11)
- **NEW**: new Tracker mode keybinding `shift-alt-<0-9>` `<0-9>` semitones down (0=10, 1=11)
- **FIX**: dim M in edit mode when metro inactive

## v3.1.0
@@ -102,6 +102,14 @@ The tracker mode clipboard is independent of text and code clipboard.
| **`alt-<right>`** | move to the very right |
| **`[`** | decrement by 1 |
| **`]`** | increment by 1 |
| **`alt-[`** | decrement by 1 semitone |
| **`alt-]`** | increment by 1 semitone |
| **`ctrl-[`** | decrement by 7 semitones |
| **`ctrl-]`** | increment by 7 semitones |
| **`shift-[`** | decrement by 12 semitones |
| **`shift-]`** | increment by 12 semitones |
| **`alt-<0-9>`** | increment by `<0-9>` semitones (0=10, 1=11) |
| **`shift-alt-<0-9>`** | decrement by `<0-9>` semitones (0=10, 1=11) |
| **`<backspace>`** | delete a digit |
| **`shift-<backspace>`** | delete an entry, shift numbers up |
| **`<enter>`** | commit edit (increase length if cursor in position after last entry) |
@@ -13,13 +13,12 @@
#include "usb_protocol_hid.h"



////////////////////////////////////////////////////////////////////////////////
// Help text ///////////////////////////////////////////////////////////////////

#define HELP_PAGES 13

#define HELP1_LENGTH 61
#define HELP1_LENGTH 68
const char* help1[HELP1_LENGTH] = { "1/13 HELP",
"[ ] NAVIGATE HELP PAGES",
"UP/DOWN TO SCROLL",
@@ -73,6 +72,13 @@ const char* help1[HELP1_LENGTH] = { "1/13 HELP",
"SPACE|TOGGLE 0/1",
"ENTER|COMMIT CHANGE",
"[ ]|NUDGE UP, DOWN",
"ALT-[ ]|SEMITONE UP, DOWN",
"CTRL-[ ]|FIFTH UP, DOWN",
"SH-[ ]|OCTAVE UP, DOWN",
"ALT-<0-9>|NUM SEMITONES UP",
"// 0 = 10 and 1 = 11",
"SH-ALT-<0-9>|NUM SEMITONES DOWN",
"// 0 = 10 and 1 = 11",
"SH-ALT-V|INSERT PASTE",
"SH-BSP|DELETE",
"SH-ENTER|DUPE INSERT",
@@ -885,11 +891,9 @@ static int prev_hit;

static bool dirty;

static bool text_search_forward(search_state_t* state,
const char* needle,
static bool text_search_forward(search_state_t* state, const char* needle,
const char** haystack, int haystack_len);
static bool text_search_reverse(search_state_t* state,
const char* needle,
static bool text_search_reverse(search_state_t* state, const char* needle,
const char** haystack, int haystack_len);


@@ -899,27 +903,29 @@ void set_help_mode() {
dirty = true;
}

bool text_search_forward(search_state_t* state,
const char* needle,
bool text_search_forward(search_state_t* state, const char* needle,
const char** haystack, int haystack_len) {
const int needle_len = strlen(needle);
for (; state->line < haystack_len; state->line++) {
const int haystack_line_len = strlen(haystack[state->line]);
for (state->ch = 0; state->ch < haystack_line_len - needle_len; state->ch++) {
if (!strncmp(needle, haystack[state->line] + state->ch, needle_len)) return true;
for (state->ch = 0; state->ch < haystack_line_len - needle_len;
state->ch++) {
if (!strncmp(needle, haystack[state->line] + state->ch, needle_len))
return true;
}
}
return false;
}

bool text_search_reverse(search_state_t* state,
const char* needle,
bool text_search_reverse(search_state_t* state, const char* needle,
const char** haystack, int haystack_len) {
const int needle_len = strlen(needle);
for (; state->line >= 0; state->line--) {
const int haystack_line_len = strlen(haystack[state->line]);
for (state->ch = haystack_line_len - needle_len; state->ch >= 0; state->ch--) {
if (!strncmp(needle, haystack[state->line] + state->ch, needle_len)) return true;
for (state->ch = haystack_line_len - needle_len; state->ch >= 0;
state->ch--) {
if (!strncmp(needle, haystack[state->line] + state->ch, needle_len))
return true;
}
}
return false;
@@ -943,19 +949,17 @@ void process_help_keys(uint8_t k, uint8_t m, bool is_held_key) {
// C-f or C-s: search forward
else if (match_ctrl(m, k, HID_F) || match_ctrl(m, k, HID_S)) {
search_result = SEARCH_RESULT_NONE;
if (search_mode == SEARCH_MODE_FWD) {
search_mode = SEARCH_MODE_NONE;
} else {
if (search_mode == SEARCH_MODE_FWD) { search_mode = SEARCH_MODE_NONE; }
else {
search_mode = SEARCH_MODE_FWD;
}
dirty = true;
}
// C-r: search in reverse
else if (match_ctrl(m, k, HID_R)) {
search_result = SEARCH_RESULT_NONE;
if (search_mode == SEARCH_MODE_REV) {
search_mode = SEARCH_MODE_NONE;
} else {
if (search_mode == SEARCH_MODE_REV) { search_mode = SEARCH_MODE_NONE; }
else {
search_mode = SEARCH_MODE_REV;
}
dirty = true;
@@ -980,9 +984,9 @@ void process_help_keys(uint8_t k, uint8_t m, bool is_held_key) {
}
}
for (int p = page_no; p < HELP_PAGES; p++) {
if (text_search_forward(&search_state,
needle,
help_pages[p], help_length[p])) {
if (text_search_forward(&search_state, needle,
help_pages[p],
help_length[p])) {
search_result = SEARCH_RESULT_HIT;
page_no = p;
offset = search_state.line;
@@ -999,42 +1003,39 @@ void process_help_keys(uint8_t k, uint8_t m, bool is_held_key) {
case SEARCH_MODE_REV: {
if (search_result == SEARCH_RESULT_HIT) {
prev_hit = search_state.line;
if (search_state.line > 0) {
search_state.line--;
}
if (search_state.line > 0) { search_state.line--; }
else {
search_result = SEARCH_RESULT_MISS;
dirty = true;
return;
}
}
for (int p = page_no; p >= 0; p--) {
if (text_search_reverse(&search_state,
needle,
help_pages[p], help_length[p])) {
if (text_search_reverse(&search_state, needle,
help_pages[p],
help_length[p])) {
search_result = SEARCH_RESULT_HIT;
page_no = p;
offset = search_state.line;
dirty = true;
return;
}
if (p > 0) {
search_state.line = help_length[p-1];
}
if (p > 0) { search_state.line = help_length[p - 1]; }
}
search_state.line = prev_hit;
search_result = SEARCH_RESULT_MISS;
dirty = true;
return;
}
default:
break;
default: break;
}
} else {
}
else {
search_result = SEARCH_RESULT_NONE;
dirty = line_editor_process_keys(&le, k, m, is_held_key);
}
} else {
}
else {
// <left> or [: previous page
if (match_no_mod(m, k, HID_LEFT) ||
match_no_mod(m, k, HID_OPEN_BRACKET)) {
@@ -1044,7 +1045,7 @@ void process_help_keys(uint8_t k, uint8_t m, bool is_held_key) {
dirty = true;
}
}
// <right> or ]: next page
// <right> or ]: next page
else if (match_no_mod(m, k, HID_RIGHT) ||
match_no_mod(m, k, HID_CLOSE_BRACKET)) {
if (page_no < HELP_PAGES - 1) {
@@ -1067,18 +1068,22 @@ uint8_t screen_refresh_help() {
if (page_no >= HELP_PAGES) page_no = HELP_PAGES - 1;

// clamp value of offset
if (offset >= help_length[page_no] - help_line_ct) offset = help_length[page_no] - help_line_ct;
if (offset >= help_length[page_no] - help_line_ct)
offset = help_length[page_no] - help_line_ct;

const char** text = help_pages[page_no];

for (uint8_t y = 0; y < help_line_ct; y++) {
if (search_result == SEARCH_RESULT_HIT
&& (y + offset) == search_state.line) {
if (search_result == SEARCH_RESULT_HIT &&
(y + offset) == search_state.line) {
region_fill(&line[y], 2);
font_string_region_clip_tab(&line[y], text[y + offset], 2, 0, 0xa, 2);
} else {
font_string_region_clip_tab(&line[y], text[y + offset], 2, 0, 0xa,
2);
}
else {
region_fill(&line[y], 0);
font_string_region_clip_tab(&line[y], text[y + offset], 2, 0, 0xa, 0);
font_string_region_clip_tab(&line[y], text[y + offset], 2, 0, 0xa,
0);
}
}

@@ -1091,14 +1096,9 @@ uint8_t screen_refresh_help() {
}

switch (search_mode) {
case SEARCH_MODE_FWD:
line_editor_draw(&le, '>', &line[7]);
break;
case SEARCH_MODE_REV:
line_editor_draw(&le, '<', &line[7]);
break;
default:
break;
case SEARCH_MODE_FWD: line_editor_draw(&le, '>', &line[7]); break;
case SEARCH_MODE_REV: line_editor_draw(&le, '<', &line[7]); break;
default: break;
}

dirty = false;
@@ -4,6 +4,9 @@
#include "globals.h"
#include "keyboard_helper.h"

// tables
#include "table.h"

// teletype
#include "teletype.h"
#include "teletype_io.h"
@@ -74,6 +77,50 @@ void pattern_down() {
dirty = true;
}

static int16_t transpose_n_value(int16_t value, int8_t interval) {
uint8_t last_note = 127;
if (interval > last_note) {
interval = last_note;
} else if (interval < -last_note) {
interval = -last_note;
}
if (value > table_n[last_note]) {
uint8_t idx = last_note;
if (interval < 0)
idx++;
return table_n[(idx + interval) % (last_note + 1)];
}
int16_t new_value = 0;
for (int i = 0; i <= last_note; i++) {
if (table_n[i] >= value) {
int8_t j = i + interval;
if (table_n[i] > value && interval > 0)
j--; // quantize to lower note
if (j > last_note) {
j = j % last_note + 1;
} else if (j < 0) {
j = j + last_note + 1;
}
new_value = table_n[j];
break;
}
}
return new_value;
}

void note_nudge(int8_t semitones) {
if (editing_number) {
edit_buffer = transpose_n_value(edit_buffer, semitones);
}
else {
int16_t pattern_val =
ss_get_pattern_val(&scene_state, pattern, base + offset);
int16_t new_val = transpose_n_value(pattern_val, semitones);
ss_set_pattern_val(&scene_state, pattern, base + offset, new_val);
}
dirty = true;
}

void process_pattern_keys(uint8_t k, uint8_t m, bool is_held_key) {
// <down>: move down
if (match_no_mod(m, k, HID_DOWN)) { pattern_down(); }
@@ -168,6 +215,44 @@ void process_pattern_keys(uint8_t k, uint8_t m, bool is_held_key) {
dirty = true;
}
}
// alt-[: decrement by 1 semitone
else if (match_alt(m, k, HID_OPEN_BRACKET)) {
note_nudge(-1);
}
// alt-]: increment by 1 semitone
else if (match_alt(m, k, HID_CLOSE_BRACKET)) {
note_nudge(1);
}
// ctrl-[: decrement by a fifth (7 semitones)
else if (match_ctrl(m, k, HID_OPEN_BRACKET)) {
note_nudge(-7);
}
// ctrl-]: increment by a fifth (7 semitones)
else if (match_ctrl(m, k, HID_CLOSE_BRACKET)) {
note_nudge(7);
}
// sh-[: decrement by 1 octave
else if (match_shift(m, k, HID_OPEN_BRACKET)) {
note_nudge(-12);
}
// sh-]: increment by 1 octave
else if (match_shift(m, k, HID_CLOSE_BRACKET)) {
note_nudge(12);
}
// alt-<0-9>: transpose up by numeric semitones
else if (mod_only_alt(m) && k >= HID_1 && k <= HID_0) {
uint8_t n = (k - HID_1 + 1); // convert HID numbers to decimal,
// leave 0 = 10 semitones
if (n == 1) n = 11; // 1 = 11 semitones since we already have alt-[ ]
note_nudge(n);
}
// sh-alt-<0-9>: transpose down by numeric semitones
else if (mod_only_shift_alt(m) && k >= HID_1 && k <= HID_0) {
uint8_t n = (k - HID_1 + 1); // convert HID numbers to decimal,
// leave 0 = 10 semitones
if (n == 1) n = 11; // 1 = 11 semitones since we already have alt-[ ]
note_nudge(-n);
}
// <backspace>: delete a digit
else if (match_no_mod(m, k, HID_BACKSPACE)) {
if (editing_number)
@@ -13,5 +13,5 @@ void set_pattern_offset(uint8_t offset);
void set_pattern_selected_value(uint8_t pattern, uint8_t offset);
void pattern_up(void);
void pattern_down(void);

void note_nudge(int8_t semitones);
#endif
ProTip! Use n and p to navigate between commits in a pull request.