Skip to content
Permalink
main
Go to file
 
 
Cannot retrieve contributors at this time
2025 lines (1887 sloc) 66.2 KB
#include "grid.h"
#include "edit_mode.h"
#include "flash.h"
#include "font.h"
#include "globals.h"
#include "live_mode.h"
#include "pattern_mode.h"
#include "preset_r_mode.h"
#include "state.h"
#include "teletype.h"
#include "teletype_io.h"
#include "timers.h"
#include "util.h"
#define GRID_MAX_KEY_PRESSED 10
#define GRID_KEY_HOLD_DELAY 700
#define GRID_KEY_REPEAT_RATE 40
#define GRID_KEY_REPEAT_RATE_CTL 120
#define GRID_ON_BRIGHTNESS 13
#define GRID_SCRIPT_TRIGGER 60
typedef enum {
G_LIVE_V,
G_LIVE_G,
G_LIVE_GF,
G_EDIT,
G_TRACKER,
G_PRESET
} grid_control_mode_t;
// clang-format off
static const u8 glyph[16][6] = {
{
0b000000,
0b000000,
0b000000,
0b000000,
0b000000,
0b000000
},
{
0b000000,
0b011110,
0b010010,
0b010010,
0b011110,
0b000000
},
{
0b000000,
0b011110,
0b010010,
0b010010,
0b010010,
0b010010
},
{
0b010010,
0b010010,
0b010010,
0b010010,
0b010010,
0b010010
},
{
0b010010,
0b010010,
0b010010,
0b010010,
0b011110,
0b000000
},
{
0b000000,
0b011111,
0b010000,
0b010000,
0b011111,
0b000000
},
{
0b000000,
0b111111,
0b000000,
0b000000,
0b111111,
0b000000
},
{
0b000000,
0b111110,
0b000010,
0b000010,
0b111110,
0b000000
},
{
0b000000,
0b011111,
0b010000,
0b010000,
0b010000,
0b010000
},
{
0b000000,
0b111111,
0b000000,
0b000000,
0b000000,
0b000000
},
{
0b000000,
0b111110,
0b000010,
0b000010,
0b000010,
0b000010
},
{
0b010000,
0b010000,
0b010000,
0b010000,
0b010000,
0b010000
},
{
0b000010,
0b000010,
0b000010,
0b000010,
0b000010,
0b000010
},
{
0b010000,
0b010000,
0b010000,
0b010000,
0b011111,
0b000000
},
{
0b000000,
0b000000,
0b000000,
0b000000,
0b111111,
0b000000
},
{
0b000010,
0b000010,
0b000010,
0b000010,
0b111110,
0b000000
}
};
// clang-format on
typedef struct {
u8 used;
u8 key;
u8 x;
u8 y;
scene_state_t *ss;
softTimer_t timer;
} hold_repeat_info;
typedef struct {
u8 on;
scene_state_t *ss;
softTimer_t timer;
} script_trigger_info;
static grid_control_mode_t tt_mode = G_LIVE_V, tt_last_mode = G_LIVE_V;
static u8 control_mode_on, tt_script, variable_edit, variable_changed;
static u8 preset_write, tracker_pressed, tracker_x, tracker_y;
static u8 tracker_changed, tracker_select, tracker_selected;
static u8 tracker_set_start, tracker_set_end;
static s16 tracker_last, variable_last;
static u16 size_x = 16, size_y = 8;
static u8 screen[GRID_MAX_DIMENSION][GRID_MAX_DIMENSION / 2];
static hold_repeat_info held_keys[GRID_MAX_KEY_PRESSED];
static u8 timers_uninitialized = 1;
static script_trigger_info script_triggers[11];
static void grid_control_refresh(scene_state_t *ss);
static u8 grid_control_process_key(scene_state_t *ss, u8 x, u8 y, u8 z,
u8 from_held);
static void hold_repeat_timer_callback(void *o);
static void grid_process_key_hold_repeat(scene_state_t *ss, u8 x, u8 y);
static void grid_screen_refresh_ctrl(scene_state_t *ss, u8 page, u8 x1, u8 y1,
u8 x2, u8 y2);
static void grid_screen_refresh_led(scene_state_t *ss, u8 full_grid, u8 page,
u8 x1, u8 y1, u8 x2, u8 y2);
static void grid_screen_refresh_info(scene_state_t *ss, u8 page, u8 x1, u8 y1,
u8 x2, u8 y2);
static bool grid_within_area(u8 x, u8 y, grid_common_t *gc);
static void grid_fill_area(u8 x, u8 y, u8 w, u8 h, s8 level);
static void grid_fill_area_scr(u8 x, u8 y, u8 w, u8 h, s8 level, u8 page);
void grid_set_control_mode(u8 control, u8 mode, scene_state_t *ss) {
if (mode == M_LIVE) {
if (grid_mode == GRID_MODE_EDIT)
tt_mode = G_LIVE_G;
else if (grid_mode == GRID_MODE_FULL)
tt_mode = G_LIVE_GF;
else
tt_mode = G_LIVE_V;
}
else if (mode == M_EDIT) {
tt_mode = G_EDIT;
tt_script = get_edit_script();
}
else if (mode == M_PATTERN) {
tt_mode = G_TRACKER;
}
else if (mode == M_PRESET_W || mode == M_PRESET_R) {
tt_mode = G_PRESET;
}
control_mode_on = control;
grid_clear_held_keys();
ss->grid.grid_dirty = 1;
}
void grid_control_refresh(scene_state_t *ss) {
size_x = monome_size_x();
size_y = monome_size_y();
u16 d = size_y == 16 ? 128 : 0;
if (size_x == 16) d += 8;
u8 mode_on = 15;
u8 mode_off = 7;
u8 exec = 15;
u8 trig = 7;
u8 kill = 11;
u8 tracker_in = 6;
u8 tracker_out = 2;
u8 tracker_on = 13;
u8 tracker_pos = 2;
u8 tracker_page_on = 11;
u8 tracker_page_off = 5;
u8 tracker_loop = 5;
u8 tracker_control = 11;
u8 preset_selected = 15;
u8 preset_unselected = 4;
u8 preset_scroll = 8;
u8 preset_load = 11;
u8 preset_save = 15;
u8 var_edit_on = 11;
u8 var_edit_off = 6;
u8 var_value_on = 11;
u8 var_value_off = 4;
u8 live_hist = 7;
u8 live_exec = 11;
u8 mute_on = 8;
u8 mute_off = 4;
u8 grid_page_on = 8;
u8 grid_page_off = 4;
u8 line_on = 8;
u8 line_off = 4;
u8 script_control = 8;
if (!monome_is_vari()) {
mode_on = 15;
mode_off = 15;
exec = 15;
trig = 15;
kill = 15;
tracker_in = 0;
tracker_out = 0;
tracker_on = 15;
tracker_page_on = 15;
tracker_page_off = 0;
tracker_loop = 15;
tracker_control = 15;
preset_selected = 15;
preset_unselected = 15;
preset_scroll = 15;
preset_load = 15;
preset_save = 15;
var_edit_on = 15;
var_edit_off = 15;
var_value_on = 15;
var_value_off = 0;
live_hist = 15;
live_exec = 15;
mute_on = 15;
mute_off = 15;
grid_page_on = 15;
grid_page_off = 15;
line_on = 15;
line_off = 15;
script_control = 15;
}
for (u16 i = 0; i < 8; i++)
for (u16 j = 0; j < 8; j++) monomeLedBuffer[d + i + (j << 4)] = 0;
if (tt_mode == G_TRACKER) {
monomeLedBuffer[d + 7] = mode_on;
u8 offset = get_pattern_offset(), in, off, rem;
for (u16 j = 0; j < 8; j++) {
for (u16 i = 0; i < 4; i++) {
in = offset + j >= ss_get_pattern_start(ss, i) &&
offset + j <= ss_get_pattern_end(ss, i);
monomeLedBuffer[d + i + 2 + (j << 4)] =
ss_get_pattern_val(ss, i, j + offset)
? tracker_on
: (in ? tracker_in : tracker_out);
}
off = offset >> 3;
rem = (offset & 7) >> 1;
monomeLedBuffer[d + (j << 4)] =
j == off ? tracker_page_on - rem
: (j == off + 1 ? tracker_page_off + rem
: tracker_page_off);
}
for (u16 i = 0; i < 4; i++) {
u8 index = ss_get_pattern_idx(ss, i);
if (index >= offset && index <= offset + 7) {
monomeLedBuffer[d + i + 2 + (index << 4)] += tracker_pos;
}
}
d += 32;
monomeLedBuffer[d + 7] = tracker_control;
d += 16;
monomeLedBuffer[d + 7] =
turtle_get_shown(&ss->turtle) ? tracker_control : tracker_loop;
d += 16;
monomeLedBuffer[d + 7] = tracker_loop;
d += 16;
monomeLedBuffer[d + 7] = tracker_loop;
d += 16;
monomeLedBuffer[d + 7] = tracker_control;
d += 16;
monomeLedBuffer[d + 7] = tracker_control;
return;
}
// mode selection
monomeLedBuffer[d] =
tt_mode == G_EDIT && tt_script == 8 ? mode_on : mode_off;
monomeLedBuffer[d + 1] =
tt_mode == G_EDIT && tt_script == 9 ? mode_on : mode_off;
monomeLedBuffer[d + 3] = tt_mode == G_LIVE_V ? mode_on : mode_off;
monomeLedBuffer[d + 4] =
tt_mode == G_LIVE_G || tt_mode == G_LIVE_GF ? mode_on : mode_off;
monomeLedBuffer[d + 6] = tt_mode == G_PRESET ? mode_on : mode_off;
monomeLedBuffer[d + 7] = mode_off;
d += 16;
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] =
tt_mode == G_EDIT && tt_script == i ? mode_on : mode_off;
d += 16;
if (tt_mode == G_PRESET) {
for (u8 j = 0; j < 25; j += 8) {
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] = i + j == preset_select
? preset_selected
: preset_unselected;
d += 16;
}
monomeLedBuffer[d + 7] = preset_scroll;
d += 16;
monomeLedBuffer[d + 2] = preset_load;
monomeLedBuffer[d + 4] = preset_save;
monomeLedBuffer[d + 7] = preset_scroll;
return;
}
monomeLedBuffer[d + 16] = ss->variables.m_act ? mute_off : mute_on;
monomeLedBuffer[d + 17] = script_triggers[10].on ? exec : kill;
monomeLedBuffer[d + 32] = script_triggers[8].on ? exec : trig;
monomeLedBuffer[d + 33] = script_triggers[9].on ? exec : trig;
if (tt_mode == G_LIVE_V) {
monomeLedBuffer[d + 3] =
variable_edit == 1 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 4] =
variable_edit == 2 ? var_edit_on : var_edit_off;
d += 16;
monomeLedBuffer[d + 3] =
variable_edit == 3 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 4] =
variable_edit == 4 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 6] = live_hist;
d += 16;
monomeLedBuffer[d + 3] =
variable_edit == 5 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 4] =
variable_edit == 6 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 6] = live_hist;
monomeLedBuffer[d + 7] = live_exec;
d += 16;
monomeLedBuffer[d + 3] =
variable_edit == 7 ? var_edit_on : var_edit_off;
monomeLedBuffer[d + 4] =
variable_edit == 8 ? var_edit_on : var_edit_off;
}
else if (tt_mode == G_LIVE_G || tt_mode == G_LIVE_GF) {
d += 16;
monomeLedBuffer[d + 7] = grid_page == 0 ? grid_page_on : grid_page_off;
d += 16;
monomeLedBuffer[d + 3] = ss->grid.rotate ? grid_page_on : grid_page_off;
monomeLedBuffer[d + 5] =
grid_show_controls ? grid_page_on : grid_page_off;
monomeLedBuffer[d + 7] = grid_page == 1 ? grid_page_on : grid_page_off;
d += 16;
}
else if (tt_mode == G_EDIT) {
d += 16;
monomeLedBuffer[d + 3] =
ss_get_script_comment(ss, tt_script, 0) ? line_off : line_on;
monomeLedBuffer[d + 4] =
ss_get_script_comment(ss, tt_script, 3) ? line_off : line_on;
monomeLedBuffer[d + 7] = script_control;
d += 16;
monomeLedBuffer[d + 3] =
ss_get_script_comment(ss, tt_script, 1) ? line_off : line_on;
monomeLedBuffer[d + 4] =
ss_get_script_comment(ss, tt_script, 4) ? line_off : line_on;
monomeLedBuffer[d + 7] = script_control;
d += 16;
monomeLedBuffer[d + 3] =
ss_get_script_comment(ss, tt_script, 2) ? line_off : line_on;
monomeLedBuffer[d + 4] =
ss_get_script_comment(ss, tt_script, 5) ? line_off : line_on;
}
d += 16;
// script mutes
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] = ss_get_mute(ss, i) ? mute_on : mute_off;
d += 16;
// triggered scripts
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] = script_triggers[i].on ? exec : trig;
if (variable_edit) {
u8 ve = variable_edit - 1;
int16_t *v = &(ss->variables.a);
if (size_x == 8) {
if (v[ve] < 0)
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] = var_value_off;
else if (v[ve] > 8)
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] = var_value_on;
else
for (u16 i = 0; i < 8; i++)
monomeLedBuffer[d + i] =
i < v[ve] ? var_value_on : var_value_off;
}
else {
d -= 8;
if (v[ve] < 0)
for (u16 i = 0; i < 16; i++)
monomeLedBuffer[d + i] = var_value_off;
else if (v[ve] > 16)
for (u16 i = 0; i < 16; i++)
monomeLedBuffer[d + i] = var_value_on;
else
for (u16 i = 0; i < 16; i++)
monomeLedBuffer[d + i] =
i < v[ve] ? var_value_on : var_value_off;
}
}
}
static void script_triggers_callback(void *o) {
script_trigger_info *st = o;
timer_remove(&st->timer);
st->on = 0;
st->ss->grid.grid_dirty = 1;
}
void grid_metro_triggered(scene_state_t *ss) {
script_triggers[8].on = 1;
script_triggers[8].ss = ss;
timer_remove(&script_triggers[8].timer);
timer_add(&script_triggers[8].timer,
min(GRID_SCRIPT_TRIGGER, ss->variables.m >> 1),
&script_triggers_callback, (void *)&script_triggers[8]);
ss->grid.grid_dirty = 1;
}
static void restore_last_mode(scene_state_t *ss) {
tt_mode = tt_last_mode;
if (tt_mode == G_EDIT) {
set_edit_mode_script(tt_script);
set_mode(M_EDIT);
}
else if (tt_mode == G_PRESET) {
set_mode(M_PRESET_R);
}
else if (tt_mode == G_LIVE_V) {
set_mode(M_LIVE);
set_live_submode(1);
}
else if (tt_mode == G_LIVE_G) {
set_mode(M_LIVE);
set_live_submode(2);
}
else if (tt_mode == G_LIVE_GF) {
set_mode(M_LIVE);
set_live_submode(3);
}
else if (tt_mode == G_TRACKER) {
tt_mode = G_TRACKER;
set_mode(M_PATTERN);
}
grid_clear_held_keys();
ss->grid.grid_dirty = 1;
}
static u8 grid_control_process_key(scene_state_t *ss, u8 x, u8 y, u8 z,
u8 from_held) {
if (size_y == 16) {
if (y < 8) return 0;
y -= 8;
}
if (variable_edit && y == 7) {
if (!z || from_held) return 1;
int16_t *v = &(ss->variables.a);
v[variable_edit - 1] = v[variable_edit - 1] == x + 1 ? 0 : x + 1;
variable_changed = 1;
set_vars_updated();
ss->grid.grid_dirty = 1;
return 1;
}
if (size_x == 16) {
if (x < 8) return 0;
x -= 8;
}
// tracker
if (tt_mode == G_TRACKER) {
u8 offset = get_pattern_offset();
if (x == 7 && y == 4) tracker_set_start = z;
if (x == 7 && y == 5) tracker_set_end = z;
if (tracker_pressed) {
s16 value =
ss_get_pattern_val(ss, tracker_x - 2, tracker_y + offset);
if (x == tracker_x && y == tracker_y && !z) {
if (!tracker_changed) {
s16 value = ss_get_pattern_val(
ss, tracker_x - 2, tracker_y + get_pattern_offset());
if (value) {
tracker_last = value;
value = 0;
}
else {
value = tracker_last ? tracker_last : 1;
}
ss_set_pattern_val(ss, tracker_x - 2, tracker_y + offset,
value);
}
tracker_pressed = 0;
tele_pattern_updated();
ss->grid.grid_dirty = 1;
return 1;
}
if (!z) return 1;
u8 updated = 0;
if (y == tracker_y) {
if (x == tracker_x + 1) {
if (value < 32767) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, value + 1);
updated = 1;
}
}
else if (x == tracker_x + 2) {
if (value < 32758) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, value + 10);
updated = 1;
}
else if (value < 32767) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, 32767);
updated = 1;
}
}
else if (x == tracker_x - 1) {
if (value > -32768) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, value - 1);
updated = 1;
}
}
else if (x == tracker_x - 2) {
if (value > -32759) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, value - 10);
updated = 1;
}
else if (value > -32768) {
ss_set_pattern_val(ss, tracker_x - 2,
tracker_y + offset, -32768);
updated = 1;
}
}
}
else if (x > 1 && x < 6) {
// set loop
if (from_held) return 1;
for (u8 i = min(tracker_x, x); i <= max(tracker_x, x); i++) {
ss_set_pattern_start(ss, i - 2, min(y, tracker_y) + offset);
ss_set_pattern_end(ss, i - 2, max(y, tracker_y) + offset);
ss_set_pattern_len(ss, i - 2,
max(y, tracker_y) + offset + 1);
}
updated = 1;
}
if (updated) {
tracker_changed = 1;
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
return 1;
}
if (tracker_select || tracker_set_start || tracker_set_end) {
if (x == 7 && y == tracker_select && !z) {
if (y == 3 && !tracker_selected) {
turtle_set_shown(&ss->turtle,
!turtle_get_shown(&ss->turtle));
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
tracker_select = 0;
}
else if (x > 1 && x < 6 && z && !from_held) {
if (tracker_select == 2) {
// set current position
tracker_selected = 1;
ss_set_pattern_idx(ss, x - 2, offset + y);
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
else if (tracker_select == 3) {
// set turtle position
tracker_selected = 1;
turtle_set_x(&ss->turtle, x - 2);
turtle_set_y(&ss->turtle, offset + y);
turtle_set_shown(&ss->turtle, 1);
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
if (tracker_set_start) {
// set start
ss_set_pattern_start(ss, x - 2, y + offset);
tracker_selected = 1;
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
if (tracker_set_end) {
// set end
ss_set_pattern_end(ss, x - 2, y + offset);
ss_set_pattern_len(ss, x - 2, y + offset + 1);
tracker_selected = 1;
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
}
return 1;
}
if (x > 1 && x < 6 && z) {
// pattern value selected
if (x != tracker_x || y != tracker_y) tracker_last = 0;
tracker_pressed = 1;
tracker_changed = 0;
tracker_x = x;
tracker_y = y;
set_pattern_selected_value(x - 2, y);
tele_pattern_updated();
ss->grid.grid_dirty = 1;
}
else if (x == 7 && y == 0 && !from_held && z) {
// exit tracker
restore_last_mode(ss);
ss->grid.grid_dirty = 1;
}
else if (x == 0 && !from_held && z) {
// select page
set_pattern_offset(y << 3);
ss->grid.grid_dirty = 1;
}
else if (x == 7 && y == 6 && z) {
u8 offset = get_pattern_offset();
if (offset) set_pattern_offset(offset - 1);
ss->grid.grid_dirty = 1;
}
else if (x == 7 && y == 7 && z) {
u8 offset = get_pattern_offset();
if (offset < 56) set_pattern_offset(offset + 1);
ss->grid.grid_dirty = 1;
}
else if (x == 7 && y > 1 && y != 4 && y != 5 && z) {
tracker_select = y;
tracker_selected = 0;
}
return 1;
}
// select page
if (y == 0) {
if (!z || from_held) return 1;
switch (x) {
case 0:
case 1:
tt_mode = G_EDIT;
tt_script = x + 8;
set_edit_mode_script(tt_script);
set_mode(M_EDIT);
ss->grid.grid_dirty = 1;
break;
case 3:
if (tt_mode != G_LIVE_V) {
tt_mode = G_LIVE_V;
set_mode(M_LIVE);
set_live_submode(1);
ss->grid.grid_dirty = 1;
}
break;
case 4:
tt_mode = tt_mode == G_LIVE_G ? G_LIVE_GF : G_LIVE_G;
set_mode(M_LIVE);
set_live_submode(tt_mode == G_LIVE_G ? 2 : 3);
ss->grid.grid_dirty = 1;
break;
case 6:
tt_last_mode = tt_mode;
tt_mode = G_PRESET;
set_mode(M_PRESET_R);
ss->grid.grid_dirty = 1;
break;
case 7:
tt_last_mode = tt_mode;
tt_mode = G_TRACKER;
set_mode(M_PATTERN);
ss->grid.grid_dirty = 1;
break;
default: break;
}
grid_clear_held_keys();
return 1;
}
// select script for editing
if (y == 1) {
if (!z || from_held) return 1;
tt_mode = G_EDIT;
tt_script = x;
set_edit_mode_script(tt_script);
set_mode(M_EDIT);
ss->grid.grid_dirty = 1;
return 1;
}
// presets
if (tt_mode == G_PRESET) {
if (!z) return 1;
if (y > 1 && y < 6 && !from_held) {
if (preset_write) {
preset_write = 0;
set_mode(M_PRESET_R);
}
process_preset_r_preset(x + ((y - 2) << 3));
ss->grid.grid_dirty = 1;
}
else if (y == 6 && x == 7) {
if (preset_write) {
preset_write = 0;
set_mode(M_PRESET_R);
}
preset_line_up();
ss->grid.grid_dirty = 1;
}
else if (y == 7 && x == 7) {
if (preset_write) {
preset_write = 0;
set_mode(M_PRESET_R);
}
preset_line_down();
ss->grid.grid_dirty = 1;
}
else if (y == 7 && x == 2 && !from_held) {
if (preset_write) {
preset_write = 0;
set_mode(M_PRESET_R);
}
else {
process_preset_r_load();
set_mode(M_PRESET_R);
restore_last_mode(ss);
}
ss->grid.grid_dirty = 1;
}
else if (y == 7 && x == 4 && !from_held) {
if (preset_write) {
flash_write(preset_select, ss, &scene_text);
flash_update_last_saved_scene(preset_select);
preset_write = 0;
restore_last_mode(ss);
}
else {
set_mode(M_PRESET_W);
preset_write = 1;
}
ss->grid.grid_dirty = 1;
}
else {
preset_write = 0;
set_mode(M_PRESET_R);
}
return 1;
}
// mutes
if (y == 6) {
if (!z || from_held) return 1;
bool muted = ss_get_mute(ss, x);
ss_set_mute(ss, x, !muted);
screen_mutes_updated();
ss->grid.grid_dirty = 1;
return 1;
}
// trigger scripts
if (y == 7) {
if (!z) return 1;
script_triggers[x].on = 1;
script_triggers[x].ss = ss;
timer_remove(&script_triggers[x].timer);
timer_add(&script_triggers[x].timer, GRID_SCRIPT_TRIGGER,
&script_triggers_callback, (void *)&script_triggers[x]);
ss->grid.grid_dirty = 1;
run_script(ss, x);
return 1;
}
if (variable_edit && y > 1 && y < 6) {
int16_t *v = &(ss->variables.a);
u8 ve = variable_edit - 1;
if (!z && x > 2 && x < 5 && variable_edit == x - 2 + ((y - 2) << 1)) {
if (!variable_changed) {
if (v[ve]) {
variable_last = v[ve];
v[ve] = 0;
}
else {
v[ve] = variable_last ? variable_last : 1;
}
}
variable_edit = 0;
set_vars_updated();
ss->grid.grid_dirty = 1;
return 1;
}
if (!z) return 1;
u8 v_x = 3 + (ve & 1);
if (x == v_x + 1) {
if (v[ve] < 32767) v[ve]++;
}
else if (x == v_x + 2) {
if (v[ve] < 32758)
v[ve] += 10;
else
v[ve] = 32767;
}
else if (x == v_x - 1) {
if (v[ve] > -32768) v[ve]--;
}
else if (x == v_x - 2) {
if (v[ve] > -32759)
v[ve] -= 10;
else
v[ve] = -32768;
}
variable_changed = 1;
set_vars_updated();
ss->grid.grid_dirty = 1;
return 1;
}
// metro on/off
if (y == 3 && x == 0 && !from_held && !z) {
ss->variables.m_act = !ss->variables.m_act;
screen_mutes_updated();
tele_metro_updated();
ss->grid.grid_dirty = 1;
return 1;
}
// kill slews/delays
if (y == 3 && x == 1 && !from_held && z) {
script_triggers[10].on = 1;
script_triggers[10].ss = ss;
timer_remove(&script_triggers[x].timer);
timer_add(&script_triggers[10].timer, GRID_SCRIPT_TRIGGER,
&script_triggers_callback, (void *)&script_triggers[10]);
clear_delays_and_slews(ss);
ss->grid.grid_dirty = 1;
return 1;
}
// trigger metro/init
if (y == 4 && x < 2 && z) {
x += 8;
script_triggers[x].on = 1;
script_triggers[x].ss = ss;
timer_remove(&script_triggers[x].timer);
timer_add(&script_triggers[x].timer, GRID_SCRIPT_TRIGGER,
&script_triggers_callback, (void *)&script_triggers[x]);
ss->grid.grid_dirty = 1;
run_script(ss, x);
return 1;
}
// live variables
if (tt_mode == G_LIVE_V) {
if (y > 1 && y < 6 && x > 2 && x < 5 && !from_held) {
variable_edit = z ? x - 2 + ((y - 2) << 1) : 0;
if (variable_edit) variable_changed = 0;
ss->grid.grid_dirty = 1;
return 1;
}
if (!z) return 1;
if (y == 3 && x == 6) { history_prev(); }
else if (y == 4 && x == 6) {
history_next();
}
else if (y == 4 && x == 7 && !from_held) {
execute_line();
}
return 1;
}
// live grid preview
if (tt_mode == G_LIVE_G || tt_mode == G_LIVE_GF) {
if (!z || from_held) return 1;
if (y == 3 && x == 7) {
grid_page = 0;
set_grid_updated();
ss->grid.grid_dirty = 1;
}
else if (y == 4 && x == 3) {
ss->grid.rotate = ss->grid.rotate == 0;
set_grid_updated();
ss->grid.grid_dirty = 1;
}
else if (y == 4 && x == 5) {
grid_show_controls = !grid_show_controls;
set_grid_updated();
ss->grid.grid_dirty = 1;
}
else if (y == 4 && x == 7) {
grid_page = 1;
set_grid_updated();
ss->grid.grid_dirty = 1;
}
return 1;
}
// edit scripts
if (tt_mode == G_EDIT) {
if (!z || from_held) return 1;
if (y > 2 && y < 6 && x > 2 && x < 5) {
u8 i = (x - 3) * 3 + y - 3;
if (i >= ss_get_script_len(ss, tt_script)) return 1;
ss_toggle_script_comment(ss, tt_script, i);
edit_mode_refresh();
ss->grid.grid_dirty = 1;
}
else if (y == 3 && x == 7) {
for (u8 i = 0; i < ss_get_script_len(ss, tt_script); i++)
ss_set_script_comment(ss, tt_script, i, 1);
edit_mode_refresh();
ss->grid.grid_dirty = 1;
}
else if (y == 4 && x == 7) {
for (u8 i = 0; i < ss_get_script_len(ss, tt_script); i++)
ss_set_script_comment(ss, tt_script, i, 0);
edit_mode_refresh();
ss->grid.grid_dirty = 1;
}
return 1;
}
return 1;
}
void grid_process_key(scene_state_t *ss, u8 _x, u8 _y, u8 z, u8 emulated) {
if (timers_uninitialized) {
timers_uninitialized = 0;
for (u8 i = 0; i < GRID_MAX_KEY_PRESSED; i++) held_keys[i].used = 0;
}
size_x = monome_size_x();
size_y = monome_size_y();
u8 x = SG.rotate && !emulated ? size_x - _x - 1 : _x;
u8 y = SG.rotate && !emulated ? size_y - _y - 1 : _y;
if (SG.clear_held) {
grid_clear_held_keys();
SG.clear_held = 0;
}
if (control_mode_on ? !emulated : true) {
u8 key = (y << 4) | x;
if (z) {
for (u8 i = 0; i < GRID_MAX_KEY_PRESSED; i++)
if (!held_keys[i].used || held_keys[i].key == key) {
held_keys[i].used = 1;
held_keys[i].key = key;
held_keys[i].x = x;
held_keys[i].y = y;
held_keys[i].ss = ss;
timer_add(&held_keys[i].timer, GRID_KEY_HOLD_DELAY,
&hold_repeat_timer_callback,
(void *)&held_keys[i]);
break;
}
}
else {
for (u8 i = 0; i < GRID_MAX_KEY_PRESSED; i++)
if (held_keys[i].key == key) {
timer_remove(&held_keys[i].timer);
held_keys[i].used = 0;
}
}
}
if (control_mode_on && !emulated)
if (grid_control_process_key(ss, x, y, z, 0)) return;
u8 refresh = 0;
u8 scripts[SCRIPT_COUNT];
for (u8 i = 0; i < SCRIPT_COUNT; i++) scripts[i] = 0;
for (u8 i = 0; i < GRID_XYPAD_COUNT; i++) {
if (z && GXYC.enabled && SG.group[GXYC.group].enabled &&
grid_within_area(x, y, &GXYC)) {
GXY.value_x = x - GXYC.x;
GXY.value_y = y - GXYC.y;
if (GXYC.script != -1) scripts[GXYC.script] = 1;
SG.latest_group = GXYC.group;
if (SG.group[GXYC.group].script != -1)
scripts[SG.group[GXYC.group].script] = 1;
refresh = 1;
}
}
u16 value;
s8 held;
if (z) {
for (u8 i = 0; i < GRID_FADER_COUNT; i++) {
if (GFC.enabled && SG.group[GFC.group].enabled &&
grid_within_area(x, y, &GFC)) {
held = -1;
if (GF.type & 1) {
for (u8 j = 0; j < GRID_MAX_KEY_PRESSED; j++)
if (held_keys[j].used && (held_keys[j].y != y) &&
grid_within_area(held_keys[j].x, held_keys[j].y,
&GFC)) {
held = j;
break;
}
}
else {
for (u8 j = 0; j < GRID_MAX_KEY_PRESSED; j++)
if (held_keys[j].used && (held_keys[j].x != x) &&
grid_within_area(held_keys[j].x, held_keys[j].y,
&GFC)) {
held = j;
break;
}
}
switch (GF.type) {
case FADER_CH_BAR:
case FADER_CH_DOT:
if (held == -1) {
GF.slide = 0;
GF.value = x - GFC.x;
}
else {
GF.slide = 1;
GF.slide_acc = 0;
GF.slide_end = x - GFC.x;
GF.slide_delta = 16;
GF.slide_dir = GF.slide_end > GF.value;
}
break;
case FADER_CV_BAR:
case FADER_CV_DOT:
if (held == -1) {
GF.slide = 0;
GF.value = GFC.h + GFC.y - y - 1;
}
else {
GF.slide = 1;
GF.slide_acc = 0;
GF.slide_end = GFC.h + GFC.y - y - 1;
GF.slide_delta = 16;
GF.slide_dir = GF.slide_end > GF.value;
}
break;
case FADER_FH_BAR:
case FADER_FH_DOT:
if (held != -1 &&
(held_keys[held].x == GFC.x ||
held_keys[held].x == (GFC.x + GFC.w - 1)))
held = -1;
if (held == -1) {
GF.slide = 0;
if (x == GFC.x) {
if (GF.value) GF.value--;
}
else if (x == GFC.x + GFC.w - 1) {
if (GF.value < GFC.level) GF.value++;
}
else {
value =
((((x - GFC.x - 1) << 1) + 1) * GFC.level) /
(GFC.w - 2);
GF.value = (value >> 1) + (value & 1);
}
}
else {
GF.slide = 1;
GF.slide_acc = 0;
if (x == GFC.x)
value = 0;
else if (x == (GFC.x + GFC.w - 1))
value = GFC.level;
else {
value =
((((x - GFC.x - 1) << 1) + 1) * GFC.level) /
(GFC.w - 2);
value = (value >> 1) + (value & 1);
}
GF.slide_end = value;
value = ((GFC.w - 2) << 4) / GFC.level;
if (value == 0) value = 1;
GF.slide_delta = value;
GF.slide_dir = GF.slide_end > GF.value;
}
break;
case FADER_FV_BAR:
case FADER_FV_DOT:
if (held != -1 &&
(held_keys[held].y == GFC.y ||
held_keys[held].y == (GFC.y + GFC.h - 1)))
held = -1;
if (held == -1) {
GF.slide = 0;
if (y == GFC.y) {
if (GF.value < GFC.level) GF.value++;
}
else if (y == GFC.y + GFC.h - 1) {
if (GF.value) GF.value--;
}
else {
value = ((((GFC.h + GFC.y - y - 2) << 1) + 1) *
GFC.level) /
(GFC.h - 2);
GF.value = (value >> 1) + (value & 1);
}
}
else {
GF.slide = 1;
GF.slide_acc = 0;
if (y == GFC.y)
value = GFC.level;
else if (y == (GFC.y + GFC.h - 1))
value = 0;
else {
value = ((((GFC.h + GFC.y - y - 2) << 1) + 1) *
GFC.level) /
(GFC.h - 2);
value = (value >> 1) + (value & 1);
}
GF.slide_end = value;
value = ((GFC.h - 2) << 4) / GFC.level;
if (value == 0) value = 1;
GF.slide_delta = value;
GF.slide_dir = GF.slide_end > GF.value;
}
break;
}
if (GFC.script != -1) scripts[GFC.script] = 1;
SG.latest_fader = i;
SG.latest_group = GFC.group;
if (SG.group[GFC.group].script != -1)
scripts[SG.group[GFC.group].script] = 1;
refresh = 1;
}
}
}
for (u16 i = 0; i < GRID_BUTTON_COUNT; i++) {
if (GBC.enabled && SG.group[GBC.group].enabled &&
grid_within_area(x, y, &GBC)) {
if (GB.latch) {
if (z) {
GB.state = !GB.state;
if (GBC.script != -1) scripts[GBC.script] = 1;
}
}
else {
GB.state = z;
if (GBC.script != -1) scripts[GBC.script] = 1;
}
SG.latest_button = i;
SG.latest_group = GBC.group;
if (SG.group[GBC.group].script != -1)
scripts[SG.group[GBC.group].script] = 1;
refresh = 1;
}
}
for (u8 i = 0; i < SCRIPT_COUNT; i++)
if (scripts[i]) run_script(ss, i);
if (refresh) SG.grid_dirty = SG.scr_dirty = 1;
}
void grid_process_key_hold_repeat(scene_state_t *ss, u8 x, u8 y) {
if (control_mode_on)
if (grid_control_process_key(ss, x, y, 1, 1)) return;
u8 refresh = 0;
u8 scripts[SCRIPT_COUNT];
for (u8 i = 0; i < SCRIPT_COUNT; i++) scripts[i] = 0;
u8 update = 0;
for (u8 i = 0; i < GRID_FADER_COUNT; i++) {
if (GFC.enabled && SG.group[GFC.group].enabled &&
grid_within_area(x, y, &GFC)) {
update = 0;
if (GF.type == FADER_FH_BAR || GF.type == FADER_FH_DOT) {
if (x == GFC.x) {
if (GF.value) GF.value--;
update = 1;
}
else if (x == GFC.x + GFC.w - 1) {
if (GF.value < GFC.level) GF.value++;
update = 1;
}
}
else if (GF.type == FADER_FV_BAR || GF.type == FADER_FV_DOT) {
if (y == GFC.y) {
if (GF.value < GFC.level) GF.value++;
update = 1;
}
else if (y == GFC.y + GFC.h - 1) {
if (GF.value) GF.value--;
update = 1;
}
}
if (update) {
if (GFC.script != -1) scripts[GFC.script] = 1;
SG.latest_fader = i;
SG.latest_group = GFC.group;
if (SG.group[GFC.group].script != -1)
scripts[SG.group[GFC.group].script] = 1;
refresh = 1;
}
}
}
for (u8 i = 0; i < SCRIPT_COUNT; i++)
if (scripts[i]) run_script(ss, i);
if (refresh) SG.grid_dirty = SG.scr_dirty = 1;
}
void hold_repeat_timer_callback(void *o) {
hold_repeat_info *hr = o;
u8 is_hold = hr->used == 1;
if (is_hold) {
timer_reset_set(&hr->timer, control_mode_on && hr->x > 7
? GRID_KEY_REPEAT_RATE_CTL
: GRID_KEY_REPEAT_RATE);
hr->used = 2;
}
grid_process_key_hold_repeat(hr->ss, hr->x, hr->y);
}
void grid_process_fader_slew(scene_state_t *ss) {
u8 refresh = 0;
u8 scripts[SCRIPT_COUNT];
for (u8 i = 0; i < SCRIPT_COUNT; i++) scripts[i] = 0;
for (u8 i = 0; i < GRID_FADER_COUNT; i++) {
if (!GF.slide) continue;
GF.slide_acc++;
if (GF.slide_acc >= GF.slide_delta) {
GF.slide_acc = 0;
if (GF.slide_dir)
GF.value++;
else
GF.value--;
if ((GF.slide_dir && GF.value >= GF.slide_end) ||
(!GF.slide_dir && GF.value <= GF.slide_end)) {
GF.value = GF.slide_end;
GF.slide = 0;
}
SG.latest_fader = i;
SG.latest_group = GFC.group;
if (GFC.script != -1) run_script(ss, GFC.script);
if (SG.group[GFC.group].script != -1)
scripts[SG.group[GFC.group].script] = 1;
refresh = 1;
}
}
for (u8 i = 0; i < SCRIPT_COUNT; i++)
if (scripts[i]) run_script(ss, i);
if (refresh) SG.grid_dirty = SG.scr_dirty = 1;
}
void grid_clear_held_keys() {
for (u8 i = 0; i < GRID_MAX_KEY_PRESSED; i++) {
held_keys[i].used = 0;
timer_remove(&held_keys[i].timer);
}
}
bool grid_within_area(u8 x, u8 y, grid_common_t *gc) {
return x >= gc->x && x < (gc->x + gc->w) && y >= gc->y &&
y < (gc->y + gc->h);
}
void grid_refresh(scene_state_t *ss) {
size_x = monome_size_x();
size_y = monome_size_y();
if (size_x == 0) size_x = 16;
if (size_y == 0) size_y = 8;
grid_fill_area(0, 0, size_x, size_y, 0);
u16 x, y;
for (u8 i = 0; i < GRID_XYPAD_COUNT; i++) {
if (GXYC.enabled && SG.group[GXYC.group].enabled) {
if (GXY.value_x || GXY.value_y) {
x = GXYC.x + GXY.value_x;
y = GXYC.y + GXY.value_y;
grid_fill_area(GXYC.x, y, GXYC.w, 1, GXYC.level);
grid_fill_area(x, GXYC.y, 1, GXYC.h, GXYC.level);
grid_fill_area(x, y, 1, 1, GRID_ON_BRIGHTNESS);
}
}
}
u16 fv, ff, fp;
for (u8 i = 0; i < GRID_FADER_COUNT; i++) {
if (GFC.enabled && SG.group[GFC.group].enabled) {
switch (GF.type) {
case FADER_CH_BAR:
grid_fill_area(GFC.x, GFC.y, GF.value + 1, GFC.h,
GRID_ON_BRIGHTNESS);
grid_fill_area(GFC.x + GF.value + 1, GFC.y,
GFC.w - GF.value - 1, GFC.h, GFC.level);
break;
case FADER_CV_BAR:
grid_fill_area(GFC.x, GFC.y, GFC.w, GFC.h - GF.value - 1,
GFC.level);
grid_fill_area(GFC.x, GFC.y + GFC.h - GF.value - 1, GFC.w,
GF.value + 1, GRID_ON_BRIGHTNESS);
break;
case FADER_CH_DOT:
grid_fill_area(GFC.x, GFC.y, GFC.w, GFC.h, GFC.level);
grid_fill_area(GFC.x + GF.value, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS);
break;
case FADER_CV_DOT:
grid_fill_area(GFC.x, GFC.y, GFC.w, GFC.h, GFC.level);
grid_fill_area(GFC.x, GFC.y + GFC.h - GF.value - 1, GFC.w,
1, GRID_ON_BRIGHTNESS);
break;
case FADER_FH_BAR:
fv = (((GFC.w - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
grid_fill_area(GFC.x, GFC.y, ff + 1, GFC.h,
GRID_ON_BRIGHTNESS);
if (fp) grid_fill_area(GFC.x + ff + 1, GFC.y, 1, GFC.h, fp);
grid_fill_area(GFC.x + GFC.w - 1, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS);
break;
case FADER_FV_BAR:
fv = (((GFC.h - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
grid_fill_area(GFC.x, GFC.y + GFC.h - ff - 1, GFC.w, ff + 1,
GRID_ON_BRIGHTNESS);
if (fp)
grid_fill_area(GFC.x, GFC.y + GFC.h - ff - 2, GFC.w, 1,
fp);
grid_fill_area(GFC.x, GFC.y, GFC.w, 1, GRID_ON_BRIGHTNESS);
break;
case FADER_FH_DOT:
grid_fill_area(GFC.x, GFC.y, 1, GFC.h, GRID_ON_BRIGHTNESS);
grid_fill_area(GFC.x + GFC.w - 1, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS);
fv = (((GFC.w - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
if (fp)
grid_fill_area(GFC.x + ff + 1, GFC.y, 1, GFC.h, fp);
else if (ff)
grid_fill_area(GFC.x + ff, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS);
break;
case FADER_FV_DOT:
grid_fill_area(GFC.x, GFC.y + GFC.h - 1, GFC.w, 1,
GRID_ON_BRIGHTNESS);
grid_fill_area(GFC.x, GFC.y, GFC.w, 1, GRID_ON_BRIGHTNESS);
fv = (((GFC.h - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
if (fp)
grid_fill_area(GFC.x, GFC.y + GFC.h - ff - 2, GFC.w, 1,
fp);
else if (ff)
grid_fill_area(GFC.x, GFC.y + GFC.h - ff - 1, GFC.w, 1,
GRID_ON_BRIGHTNESS);
break;
}
}
}
for (u16 i = 0; i < GRID_BUTTON_COUNT; i++)
if (GBC.enabled && SG.group[GBC.group].enabled)
grid_fill_area(GBC.x, GBC.y, GBC.w, GBC.h,
GB.state ? GRID_ON_BRIGHTNESS : GBC.level);
u16 led;
for (u16 i = 0; i < size_x; i++)
for (u16 j = 0; j < size_y; j++) {
led = (j << 4) + i;
if (led >= MONOME_MAX_LED_BYTES) continue;
if (SG.leds[i][j] >= 0)
monomeLedBuffer[led] = SG.leds[i][j];
else if (SG.leds[i][j] == LED_DIM) {
if (monomeLedBuffer[led] > 3)
monomeLedBuffer[led] -= 3;
else
monomeLedBuffer[led] = 0;
}
else if (SG.leds[i][j] == LED_BRI) {
if (monomeLedBuffer[led] > 12)
monomeLedBuffer[led] = 15;
else
monomeLedBuffer[led] += 3;
}
if (monomeLedBuffer[led] < SG.dim)
monomeLedBuffer[led] = 0;
else
monomeLedBuffer[led] -= SG.dim;
}
if (control_mode_on) grid_control_refresh(ss);
u8 temp;
if (SG.rotate) {
if (size_x == 8) {
u16 a, b;
for (u16 row = 0; row < 4; row++)
for (u16 col = 0; col < 8; col++) {
a = (row << 4) + col;
b = ((7 - row) << 4) + 7 - col;
temp = monomeLedBuffer[a];
monomeLedBuffer[a] = monomeLedBuffer[b];
monomeLedBuffer[b] = temp;
}
}
else {
u16 total = size_x * size_y;
if (total > MONOME_MAX_LED_BYTES) total = MONOME_MAX_LED_BYTES;
for (u16 i = 0; i < (total >> 1); i++) {
temp = monomeLedBuffer[i];
monomeLedBuffer[i] = monomeLedBuffer[total - i - 1];
monomeLedBuffer[total - i - 1] = temp;
}
}
}
SG.grid_dirty = 0;
}
void grid_fill_area(u8 x, u8 y, u8 w, u8 h, s8 level) {
if (level == LED_OFF) return;
u16 index;
u16 x_end = min(size_x, x + w);
u16 y_end = min(size_y, y + h);
if (level == LED_DIM) {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y; _y < y_end; _y++) {
index = _x + (_y << 4);
if (index < MONOME_MAX_LED_BYTES) {
if (monomeLedBuffer[index] > 3)
monomeLedBuffer[index] -= 3;
else
monomeLedBuffer[index] = 0;
}
}
}
else if (level == LED_BRI) {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y; _y < y_end; _y++) {
index = _x + (_y << 4);
if (index < MONOME_MAX_LED_BYTES) {
if (monomeLedBuffer[index] > 12)
monomeLedBuffer[index] = 15;
else
monomeLedBuffer[index] += 3;
}
}
}
else {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y; _y < y_end; _y++) {
index = _x + (_y << 4);
if (index < MONOME_MAX_LED_BYTES)
monomeLedBuffer[index] = level;
}
}
}
///////////////////////////////////////// screen functions
void grid_screen_refresh(scene_state_t *ss, screen_grid_mode mode, u8 page,
u8 ctrl, u8 x1, u8 y1, u8 x2, u8 y2) {
switch (mode) {
case GRID_MODE_EDIT:
grid_screen_refresh_led(ss, 0, page, x1, y1, x2, y2);
if (ctrl) grid_screen_refresh_ctrl(ss, page, x1, y1, x2, y2);
grid_screen_refresh_info(ss, page, x1, y1, x2, y2);
break;
case GRID_MODE_FULL:
grid_screen_refresh_led(ss, 1, page, x1, y1, x2, y2);
break;
case GRID_MODE_OFF:
case GRID_MODE_LAST: break;
}
SG.scr_dirty = 0;
}
void grid_screen_refresh_ctrl(scene_state_t *ss, u8 page, u8 x1, u8 y1, u8 x2,
u8 y2) {
grid_fill_area_scr(0, 0, GRID_MAX_DIMENSION, GRID_MAX_DIMENSION, 0, 0);
u8 last_x, last_y;
for (u16 i = 0; i < GRID_BUTTON_COUNT; i++) {
if (!SG.group[GBC.group].enabled || !GBC.enabled) continue;
last_x = GBC.x + GBC.w - 1;
last_y = GBC.y + GBC.h - 1;
if (GBC.w == 1 && GBC.h == 1) {
grid_fill_area_scr(GBC.x, GBC.y, 1, 1, 1, page);
}
else if (GBC.w == 1 && GBC.h > 1) {
grid_fill_area_scr(GBC.x, GBC.y, 1, 1, 2, page);
grid_fill_area_scr(GBC.x, GBC.y + 1, 1, GBC.h - 2, 3, page);
grid_fill_area_scr(GBC.x, last_y, 1, 1, 4, page);
}
else if (GBC.w > 1 && GBC.h == 1) {
grid_fill_area_scr(GBC.x, GBC.y, 1, 1, 5, page);
grid_fill_area_scr(GBC.x + 1, GBC.y, GBC.w - 2, 1, 6, page);
grid_fill_area_scr(last_x, GBC.y, 1, 1, 7, page);
}
else {
grid_fill_area_scr(GBC.x, GBC.y, 1, 1, 8, page);
grid_fill_area_scr(GBC.x + 1, GBC.y, GBC.w - 2, 1, 9, page);
grid_fill_area_scr(last_x, GBC.y, 1, 1, 10, page);
grid_fill_area_scr(GBC.x, GBC.y + 1, 1, GBC.h - 2, 11, page);
grid_fill_area_scr(last_x, GBC.y + 1, 1, GBC.h - 2, 12, page);
grid_fill_area_scr(GBC.x, last_y, 1, 1, 13, page);
grid_fill_area_scr(GBC.x + 1, last_y, GBC.w - 2, 1, 14, page);
grid_fill_area_scr(last_x, last_y, 1, 1, 15, page);
}
}
for (u16 i = 0; i < GRID_FADER_COUNT; i++) {
if (!SG.group[GFC.group].enabled || !GFC.enabled) continue;
last_x = GFC.x + GFC.w - 1;
last_y = GFC.y + GFC.h - 1;
if (GFC.w == 1 && GFC.h == 1) {
grid_fill_area_scr(GFC.x, GFC.y, 1, 1, 1, page);
}
else if (GFC.w == 1 && GFC.h > 1) {
grid_fill_area_scr(GFC.x, GFC.y, 1, 1, 2, page);
grid_fill_area_scr(GFC.x, GFC.y + 1, 1, GFC.h - 2, 3, page);
grid_fill_area_scr(GFC.x, last_y, 1, 1, 4, page);
}
else if (GFC.w > 1 && GFC.h == 1) {
grid_fill_area_scr(GFC.x, GFC.y, 1, 1, 5, page);
grid_fill_area_scr(GFC.x + 1, GFC.y, GFC.w - 2, 1, 6, page);
grid_fill_area_scr(last_x, GFC.y, 1, 1, 7, page);
}
else {
grid_fill_area_scr(GFC.x, GFC.y, 1, 1, 8, page);
grid_fill_area_scr(GFC.x + 1, GFC.y, GFC.w - 2, 1, 9, page);
grid_fill_area_scr(last_x, GFC.y, 1, 1, 10, page);
grid_fill_area_scr(GFC.x, GFC.y + 1, 1, GFC.h - 2, 11, page);
grid_fill_area_scr(last_x, GFC.y + 1, 1, GFC.h - 2, 12, page);
grid_fill_area_scr(GFC.x, last_y, 1, 1, 13, page);
grid_fill_area_scr(GFC.x + 1, last_y, GFC.w - 2, 1, 14, page);
grid_fill_area_scr(last_x, last_y, 1, 1, 15, page);
}
}
u8 l, _y, __y;
u16 d;
for (u16 y = 0; y < 48; y++) {
l = y >> 3;
d = 10 + ((y & 7) << 7);
_y = y / 6;
__y = y % 6;
for (u16 x = 0; x < 96; x++)
if ((1 << (5 - (x % 6))) & glyph[screen[x / 6][_y]][__y])
line[l].data[x + d] = 10;
}
return;
}
void grid_screen_refresh_led(scene_state_t *ss, u8 full_grid, u8 page, u8 x1,
u8 y1, u8 x2, u8 y2) {
grid_fill_area_scr(0, 0, GRID_MAX_DIMENSION, GRID_MAX_DIMENSION, 0, 0);
u16 x, y;
for (u8 i = 0; i < GRID_XYPAD_COUNT; i++) {
if (GXYC.enabled && SG.group[GXYC.group].enabled) {
if (GXY.value_x || GXY.value_y) {
x = GXYC.x + GXY.value_x;
y = GXYC.y + GXY.value_y;
grid_fill_area_scr(GXYC.x, y, GXYC.w, 1, GXYC.level, page);
grid_fill_area_scr(x, GXYC.y, 1, GXYC.h, GXYC.level, page);
grid_fill_area_scr(x, y, 1, 1, GRID_ON_BRIGHTNESS, page);
}
}
}
u16 fv, ff, fp;
for (u8 i = 0; i < GRID_FADER_COUNT; i++) {
if (GFC.enabled && SG.group[GFC.group].enabled) {
switch (GF.type) {
case FADER_CH_BAR:
grid_fill_area_scr(GFC.x, GFC.y, GF.value + 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
grid_fill_area_scr(GFC.x + GF.value + 1, GFC.y,
GFC.w - GF.value - 1, GFC.h, GFC.level,
page);
break;
case FADER_CV_BAR:
grid_fill_area_scr(GFC.x, GFC.y, GFC.w,
GFC.h - GF.value - 1, GFC.level, page);
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - GF.value - 1,
GFC.w, GF.value + 1, GRID_ON_BRIGHTNESS,
page);
break;
case FADER_CH_DOT:
grid_fill_area_scr(GFC.x, GFC.y, GFC.w, GFC.h, GFC.level,
page);
grid_fill_area_scr(GFC.x + GF.value, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
break;
case FADER_CV_DOT:
grid_fill_area_scr(GFC.x, GFC.y, GFC.w, GFC.h, GFC.level,
page);
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - GF.value - 1,
GFC.w, 1, GRID_ON_BRIGHTNESS, page);
break;
case FADER_FH_BAR:
fv = (((GFC.w - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
grid_fill_area_scr(GFC.x, GFC.y, ff + 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
if (fp)
grid_fill_area_scr(GFC.x + ff + 1, GFC.y, 1, GFC.h, fp,
page);
grid_fill_area_scr(GFC.x + GFC.w - 1, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
break;
case FADER_FV_BAR:
fv = (((GFC.h - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - ff - 1, GFC.w,
ff + 1, GRID_ON_BRIGHTNESS, page);
if (fp)
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - ff - 2, GFC.w,
1, fp, page);
grid_fill_area_scr(GFC.x, GFC.y, GFC.w, 1,
GRID_ON_BRIGHTNESS, page);
break;
case FADER_FH_DOT:
grid_fill_area_scr(GFC.x, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
grid_fill_area_scr(GFC.x + GFC.w - 1, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
fv = (((GFC.w - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
if (fp)
grid_fill_area_scr(GFC.x + ff + 1, GFC.y, 1, GFC.h, fp,
page);
else if (ff)
grid_fill_area_scr(GFC.x + ff, GFC.y, 1, GFC.h,
GRID_ON_BRIGHTNESS, page);
break;
case FADER_FV_DOT:
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - 1, GFC.w, 1,
GRID_ON_BRIGHTNESS, page);
grid_fill_area_scr(GFC.x, GFC.y, GFC.w, 1,
GRID_ON_BRIGHTNESS, page);
fv = (((GFC.h - 2) << 4) * GF.value) / GFC.level;
ff = fv >> 4;
fp = fv & 15;
if (fp)
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - ff - 2, GFC.w,
1, fp, page);
else if (ff)
grid_fill_area_scr(GFC.x, GFC.y + GFC.h - ff - 1, GFC.w,
1, GRID_ON_BRIGHTNESS, page);
break;
}
}
}
for (u16 i = 0; i < GRID_BUTTON_COUNT; i++)
if (GBC.enabled && SG.group[GBC.group].enabled)
grid_fill_area_scr(GBC.x, GBC.y, GBC.w, GBC.h,
GB.state ? GRID_ON_BRIGHTNESS : GBC.level, page);
u16 pd = page ? 8 : 0;
s8 l;
for (u16 i = 0; i < GRID_MAX_DIMENSION; i++)
for (u16 j = 0; j < GRID_MAX_DIMENSION / 2; j++) {
l = SG.leds[i][j + pd];
if (l >= 0)
screen[i][j] = l;
else if (l == LED_DIM) {
if (screen[i][j] > 3)
screen[i][j] -= 3;
else
screen[i][j] = 0;
}
else if (l == LED_BRI) {
if (screen[i][j] > 12)
screen[i][j] = 15;
else
screen[i][j] += 3;
}
}
u16 _y, cell, size, left;
if (full_grid) {
cell = 8;
size = 5;
left = 0;
for (int i = 0; i < 8; i++) region_fill(&line[i], 0);
}
else {
cell = 6;
size = 4;
left = 10;
for (int i = 0; i < 6; i++) region_fill(&line[i], 0);
}
u8 _line;
u16 _data;
for (u16 x = 0; x < GRID_MAX_DIMENSION; x++)
for (u16 y = 0; y < GRID_MAX_DIMENSION / 2; y++)
for (u16 j = 0; j < size; j++) {
_y = y * cell + j + 1;
_line = _y >> 3;
for (u16 i = 0; i < size; i++) {
_data = left + x * cell + i + ((_y & 7) << 7) + 1;
if (_line > 7 || _data > 1023) continue;
if (screen[x][y] == 0) {
if (i == 0 || i == size - 1 || j == 0 || j == size - 1)
line[_line].data[_data] = 1;
}
else
line[_line].data[_data] = screen[x][y];
}
}
// draw selected area
u8 _x1, _x2;
u16 _y1, _y2;
_x1 = min(x1, x2) * cell;
_y1 = min(y1, y2) * cell;
if (full_grid) {
_x2 = (max(x1, x2) + 1) * cell - 2;
_y2 = (max(y1, y2) + 1) * cell - 2;
}
else {
_x2 = (max(x1, x2) + 1) * cell - 1;
_y2 = (max(y1, y2) + 1) * cell - 1;
}
u8 show_y1, show_y2;
show_y1 = show_y2 = true;
u16 p = cell << 3;
if (page) {
if (_y2 < p) return;
if (_y1 < p) {
show_y1 = false;
_y1 = p;
};
_y1 -= p;
_y2 -= p;
}
else {
if (_y1 >= p) return;
if (_y2 >= p) {
show_y2 = false;
_y2 = p - 1;
}
}
if (show_y1) {
_line = _y1 >> 3;
_data = left + ((_y1 & 7) << 7);
for (u16 x = _x1; x <= _x2; x++)
line[_line].data[_data + x] = x & 1 ? 4 : 15;
}
if (show_y2) {
_line = _y2 >> 3;
_data = left + ((_y2 & 7) << 7);
if (full_grid)
for (u16 x = _x1 + 1; x <= _x2; x++)
line[_line].data[_data + x] = x & 1 ? 4 : 15;
else
for (u16 x = _x1 + 1; x <= _x2; x++)
line[_line].data[_data + x] = x & 1 ? 15 : 4;
}
if (full_grid)
for (u16 y = _y1; y <= _y2; y++) {
line[y >> 3].data[left + ((y & 7) << 7) + _x1] =
line[y >> 3].data[left + ((y & 7) << 7) + _x2] = y & 1 ? 4 : 15;
}
else
for (u16 y = _y1; y <= _y2; y++) {
line[y >> 3].data[left + ((y & 7) << 7) + _x1] = y & 1 ? 4 : 15;
line[y >> 3].data[left + ((y & 7) << 7) + _x2] = y & 1 ? 15 : 4;
}
}
static void grid_screen_refresh_info(scene_state_t *ss, u8 page, u8 x1, u8 y1,
u8 x2, u8 y2) {
char s[32];
u8 area_x, area_y, area_w, area_h;
if (x1 < x2) {
area_x = x1;
area_w = x2 + 1 - x1;
}
else {
area_x = x2;
area_w = x1 + 1 - x2;
}
if (y1 < y2) {
area_y = y1;
area_h = y2 + 1 - y1;
}
else {
area_y = y2;
area_h = y1 + 1 - y2;
}
s[1] = 0;
s[0] = 'G';
font_string_region_clip_right(&line[0], s, 127, 0, 1, 0);
s[0] = 'X';
font_string_region_clip_right(&line[2], s, 127, 0, 1, 0);
s[0] = 'Y';
font_string_region_clip_right(&line[3], s, 127, 0, 1, 0);
s[0] = 'W';
font_string_region_clip_right(&line[4], s, 128, 0, 1, 0);
s[0] = 'H';
font_string_region_clip_right(&line[5], s, 127, 0, 1, 0);
itoa(ss->grid.current_group, s, 10);
font_string_region_clip_right(&line[0], s, 117, 0, 8, 0);
itoa(area_x, s, 10);
font_string_region_clip_right(&line[2], s, 117, 0, 8, 0);
itoa(area_y, s, 10);
font_string_region_clip_right(&line[3], s, 117, 0, 8, 0);
itoa(area_w, s, 10);
font_string_region_clip_right(&line[4], s, 117, 0, 8, 0);
itoa(area_h, s, 10);
font_string_region_clip_right(&line[5], s, 117, 0, 8, 0);
for (u16 j = 0; j < 9; j += 2) line[j >> 3].data[119 + ((j & 7) << 7)] = 1;
for (u16 j = 17; j < 48; j += 2)
line[j >> 3].data[119 + ((j & 7) << 7)] = 1;
// icons
if (page == 0) {
for (u16 i = 0; i < 5; i++)
line[0].data[i] = line[0].data[i + 128] = 10;
line[0].data[0 + 256] = 1;
line[0].data[4 + 256] = 1;
line[0].data[0 + 384] = 1;
line[0].data[4 + 384] = 1;
for (u16 i = 512; i < 517; i++) line[0].data[i] = 1;
}
else {
for (u16 i = 0; i < 5; i++) line[0].data[i] = 1;
line[0].data[0 + 128] = 1;
line[0].data[4 + 128] = 1;
line[0].data[0 + 256] = 1;
line[0].data[4 + 256] = 1;
for (u16 i = 384; i < 389; i++)
line[0].data[i] = line[0].data[i + 128] = 10;
}
u8 l = ss->grid.rotate ? 10 : 1;
line[1].data[0 + 0] = l;
line[1].data[1 + 0] = l;
line[1].data[2 + 0] = l;
line[1].data[2 + 128] = l;
line[1].data[0 + 256] = l;
line[1].data[2 + 256] = l;
line[1].data[4 + 256] = l;
line[1].data[1 + 384] = l;
line[1].data[2 + 384] = l;
line[1].data[3 + 384] = l;
line[1].data[2 + 512] = l;
}
void grid_fill_area_scr(u8 x, u8 y, u8 w, u8 h, s8 level, u8 page) {
if (level == LED_OFF) return;
u16 x_end = min(GRID_MAX_DIMENSION, x + w);
u16 y1, y2;
y1 = y;
y2 = min(GRID_MAX_DIMENSION, y + h) - 1;
if (page) {
if (y2 < 8) return;
if (y1 < 8) y1 = 8;
y1 -= 8;
y2 -= 8;
}
else {
if (y1 >= 8) return;
if (y2 >= 8) y2 = 7;
}
if (level == LED_DIM) {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y1; _y <= y2; _y++)
if (screen[_x][_y] > 3)
screen[_x][_y] -= 3;
else
screen[_x][_y] = 0;
}
else if (level == LED_BRI) {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y1; _y <= y2; _y++)
if (screen[_x][_y] > 12)
screen[_x][_y] = 15;
else
screen[_x][_y] += 3;
}
else {
for (u16 _x = x; _x < x_end; _x++)
for (u16 _y = y1; _y <= y2; _y++) screen[_x][_y] = level;
}
}