volatile uint8_t button = 0;
volatile uint8_t button_old = 0;
volatile uint8_t button_new = 0;
+volatile uint8_t button_hold = 0;
volatile uint16_t button_count = 0;
volatile uint16_t button_hold_count = 0;
volatile uint16_t button_y_count = 0;
-volatile uint8_t jog = 0;
-volatile uint8_t jog_old = 0;
-volatile uint8_t jog_new = 0;
+volatile uint16_t jog = 0;
+volatile uint16_t jog_old = 0;
+volatile uint16_t jog_new = 0;
+
+volatile uint16_t jog_timer = 0;
volatile uint16_t gui_event[N_GUI_EVENT];
volatile uint8_t gui_event_r = 0;
/* handling inputs */
+inline void int_jog_timer (void) // count time since last jog action
+{
+ if (jog_timer < JOG_TIME_BITS)
+ ++jog_timer;
+}
+
inline void int_jog (void) // interrupt from rotary dial
{
jog_old = jog_new;
jog_new = GET_JOG();
- if(!(jog_new & 0x1)) //full position
+ if(!(jog_new & JOG_L)) //full position
{
if(jog_new != jog) //new position, not return
{
jog = jog_new;
- add_gui_event(EVENT_JOG | ((jog_new - jog_old) & 0x3));
+ add_gui_event(
+ EVENT_JOG |
+ ((jog_new - jog_old) & JOG_BITS) |
+ jog_timer & JOG_TIME_BITS
+ );
+ jog_timer = 0;
}
}
}
+inline uint16_t gui_jog_boost(const uint16_t time)
+{
+ if (time <= JOG_X_20)
+ return 20;
+ if (time <= JOG_X_19)
+ return 19;
+ if (time <= JOG_X_18)
+ return 18;
+ if (time <= JOG_X_17)
+ return 17;
+ if (time <= JOG_X_16)
+ return 16;
+ if (time <= JOG_X_15)
+ return 15;
+ if (time <= JOG_X_14)
+ return 14;
+ if (time <= JOG_X_13)
+ return 13;
+ if (time <= JOG_X_12)
+ return 12;
+ if (time <= JOG_X_11)
+ return 11;
+ if (time <= JOG_X_10)
+ return 10;
+ if (time <= JOG_X_9)
+ return 9;
+ if (time <= JOG_X_8)
+ return 8;
+ if (time <= JOG_X_7)
+ return 7;
+ if (time <= JOG_X_6)
+ return 6;
+ if (time <= JOG_X_5)
+ return 5;
+ if (time <= JOG_X_4)
+ return 4;
+ if (time <= JOG_X_3)
+ return 3;
+ if (time <= JOG_X_2)
+ return 2;
+ return 1;
+}
+
inline void int_button_abcdef(void) // interrupt from button ADC
{
uint8_t adc;
if (press)
add_gui_event(EVENT_PRESS | press);
if (release)
- add_gui_event(EVENT_RELEASE | release);
+ {
+ if (button_hold & release)
+ {
+ add_gui_event(EVENT_RELEASE | EVENT_WAS_HOLD | release);
+ button_hold &= (~release);
+ }
+ else
+ add_gui_event(EVENT_RELEASE | release);
+ }
}
}
}
if (button_hold_count == BUTTON_HOLD)
{
if(button)
+ {
+ button_hold = button;
add_gui_event(EVENT_HOLD | button);
+ }
}
}
}
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
if (gui_page < (N_PAGES - 1))
++gui_page;
else if((event & EVENT_BITS) == EVENT_JOG)
{
oldcursor = gui_name_cursor;
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
if (gui_name_cursor < gui_name_maxcursor)
++gui_name_cursor;
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
if (gui_page < (N_PAGES - 1))
++gui_page;
inline void gui_event_options (const uint16_t event)
{
- if((event & EVENT_BITS) == EVENT_RELEASE)
+ if((event & EVENT_BITS) == EVENT_HOLD)
+ {
+ if (event & BUTTON_A)
+ {
+ set_tuning(DEFAULT_TUNING);
+ make_text_tuning();
+ lcd_update_button(0, text_tuning);
+ }
+ else if (event & BUTTON_B)
+ {
+ set_transp(0);
+ make_text_transpose();
+ lcd_update_button(1, text_transpose);
+ }
+ else if (event & BUTTON_C)
+ {
+ midi_id = N_MIDI_ID;
+ ctrl_update_midi();
+ make_text_midi_in();
+ lcd_update_button(2, text_midi_in);
+ }
+ else if (event & BUTTON_D)
+ {
+ midi_id_out = 0;
+ ctrl_update_midi();
+ make_text_midi_out();
+ lcd_update_button(3, text_midi_out);
+ }
+ // no long press on button E
+ else if (event & BUTTON_F)
+ gui_gotostate_total_reset();
+ }
+ else if((event & EVENT_BITS) == EVENT_RELEASE)
{
if (event & BUTTON_X)
gui_gotostate_wave();
else if (event & BUTTON_Y)
gui_gotostate_select();
else if (event & BUTTON_A)
- gui_gotostate_tuning();
+ {
+ if (!(event & EVENT_WAS_HOLD))
+ gui_gotostate_tuning();
+ }
else if (event & BUTTON_B)
- gui_gotostate_transpose();
+ {
+ if (!(event & EVENT_WAS_HOLD))
+ gui_gotostate_transpose();
+ }
else if (event & BUTTON_C)
- gui_gotostate_midi_id();
+ {
+ if (!(event & EVENT_WAS_HOLD))
+ gui_gotostate_midi_id();
+ }
else if (event & BUTTON_D)
- gui_gotostate_midi_id_out();
+ {
+ if (!(event & EVENT_WAS_HOLD))
+ gui_gotostate_midi_id_out();
+ }
else if (event & BUTTON_E)
{
if (midi_pedal_en)
}
ctrl_update_midi();
}
- else if (event & BUTTON_F)
- gui_gotostate_total_reset();
+ // no short press on button F - long press is needed
}
}
inline void gui_event_tuning (const uint16_t event)
{
- if((event & EVENT_BITS) == EVENT_RELEASE)
+ if((event & EVENT_BITS) == EVENT_HOLD)
+ {
+ if (event & BUTTON_A)
+ {
+ set_tuning(DEFAULT_TUNING);
+ make_text_tuning();
+ lcd_update_button(0, text_tuning);
+ }
+ }
+ else if((event & EVENT_BITS) == EVENT_RELEASE)
{
- if (event & (BUTTON_X | BUTTON_Y | BUTTON_A))
+ if (
+ (event & (BUTTON_X | BUTTON_Y)) ||
+ ((event & BUTTON_A) && !(event & EVENT_WAS_HOLD))
+ )
gui_gotostate_options();
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
- set_tuning(tuning + 1);
+ set_tuning(tuning + gui_jog_boost(event & JOG_TIME_BITS));
}
else
{
- set_tuning(tuning - 1);
+ set_tuning(tuning - gui_jog_boost(event & JOG_TIME_BITS));
}
make_text_tuning();
}
}
-// TRANSPOSE: shift by -6 to 6 semitones
+// TRANSPOSE: shift by -12 to 12 semitones
inline void gui_gotostate_transpose (void)
{
inline void gui_event_transpose (const uint16_t event)
{
- if((event & EVENT_BITS) == EVENT_RELEASE)
+ if((event & EVENT_BITS) == EVENT_HOLD)
{
- if (event & (BUTTON_X | BUTTON_Y | BUTTON_B))
+ if (event & BUTTON_B)
+ {
+ set_transp(0);
+ make_text_transpose();
+ lcd_update_button(1, text_transpose);
+ }
+ }
+ else if((event & EVENT_BITS) == EVENT_RELEASE)
+ {
+ if (
+ (event & (BUTTON_X | BUTTON_Y)) ||
+ ((event & BUTTON_B) && !(event & EVENT_WAS_HOLD))
+ )
gui_gotostate_options();
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
- if (transp<6)
+ if (transp<12)
set_transp(transp + 1);
}
else
{
- if (transp>-6)
+ if (transp>-12)
set_transp(transp - 1);
}
inline void gui_event_midi_id (const uint16_t event)
{
- if((event & EVENT_BITS) == EVENT_RELEASE)
+ if((event & EVENT_BITS) == EVENT_HOLD)
+ {
+ if (event & BUTTON_C)
+ {
+ midi_id = N_MIDI_ID;
+ ctrl_update_midi();
+ make_text_midi_in();
+ lcd_update_button(2, text_midi_in);
+ }
+ }
+ else if((event & EVENT_BITS) == EVENT_RELEASE)
{
- if (event & (BUTTON_X | BUTTON_Y | BUTTON_C))
+ if (
+ (event & (BUTTON_X | BUTTON_Y)) ||
+ ((event & BUTTON_C) && !(event & EVENT_WAS_HOLD))
+ )
gui_gotostate_options();
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
if (midi_id < N_MIDI_ID)
++midi_id;
inline void gui_event_midi_id_out (const uint16_t event)
{
- if((event & EVENT_BITS) == EVENT_RELEASE)
+ if((event & EVENT_BITS) == EVENT_HOLD)
+ {
+ if (event & BUTTON_D)
+ {
+ midi_id_out = 0;
+ ctrl_update_midi();
+ make_text_midi_out();
+ lcd_update_button(3, text_midi_out);
+ }
+ }
+ else if((event & EVENT_BITS) == EVENT_RELEASE)
{
- if (event & (BUTTON_X | BUTTON_Y | BUTTON_D))
+ if (
+ (event & (BUTTON_X | BUTTON_Y)) ||
+ ((event & BUTTON_D) && !(event & EVENT_WAS_HOLD))
+ )
gui_gotostate_options();
}
else if((event & EVENT_BITS) == EVENT_JOG)
{
- if ((event & ~EVENT_BITS) == JOG_PLUS)
+ if ((event & JOG_BITS) == JOG_PLUS)
{
if (midi_id_out < N_MIDI_ID-1)
++midi_id_out;
else
++gui_event_r;
+ if ((event & EVENT_BITS) == EVENT_JOG)
+ {
+ debug_string("JOG", 1);
+ if ((event & JOG_BITS) == JOG_PLUS)
+ debug_string("+", 1);
+ if ((event & JOG_BITS) == JOG_MINUS)
+ debug_string("-", 1);
+ debug_dec(event & JOG_TIME_BITS, 1, 0);
+ }
+ else
+ {
+ if (event & BUTTON_A)
+ debug_string("A", 1);
+ if (event & BUTTON_B)
+ debug_string("B", 1);
+ if (event & BUTTON_C)
+ debug_string("C", 1);
+ if (event & BUTTON_D)
+ debug_string("D", 1);
+ if (event & BUTTON_E)
+ debug_string("E", 1);
+ if (event & BUTTON_F)
+ debug_string("F", 1);
+ if (event & BUTTON_X)
+ debug_string("X", 1);
+ if (event & BUTTON_Y)
+ debug_string("Y", 1);
+ if ((event & EVENT_BITS) == EVENT_PRESS)
+ debug_string(" PRESS", 1);
+ if ((event & EVENT_BITS) == EVENT_RELEASE)
+ debug_string(" RELEASE", 1);
+ if ((event & EVENT_BITS) == EVENT_HOLD)
+ debug_string(" HOLD", 1);
+ if (event & EVENT_WAS_HOLD)
+ debug_string(" (WAS HOLD)", 1);
+ }
+ debug_string("\r\n", 1);
+
// execute appropriate event handler for current state
switch (gui_state)
{
/* GUI */
/* Encoding of this file is ISO 8859-2 */
/*
-Copyright 2021, 2022 Balthasar Szczepañski
+Copyright 2021, 2022, 2024 Balthasar Szczepañski
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#include <stdint.h>
#include "klavirko-ui.h"
-#define GET_JOG() ((JOG_A ? 0x1 : 0x0) ^ (JOG_B ? 0x3 : 0x0))
-
#define BUTTON_DEBOUNCE 4
#define BUTTON_HOLD 680
#define BUTTON_THR_5 147
#define BUTTON_THR_6 208
-#define JOG_PLUS 1
-#define JOG_MINUS 3
+#define JOG_BITS 0x0C00
+#define JOG_L 0x0400
+#define JOG_H 0x0C00
+#define JOG_PLUS 0x0400
+#define JOG_MINUS 0x0C00
+
+#define JOG_X_20 06
+#define JOG_X_19 14
+#define JOG_X_18 22
+#define JOG_X_17 30
+#define JOG_X_16 38
+#define JOG_X_15 46
+#define JOG_X_14 54
+#define JOG_X_13 62
+#define JOG_X_12 70
+#define JOG_X_11 78
+#define JOG_X_10 86
+#define JOG_X_9 94
+#define JOG_X_8 102
+#define JOG_X_7 110
+#define JOG_X_6 118
+#define JOG_X_5 126
+#define JOG_X_4 134
+#define JOG_X_3 142
+#define JOG_X_2 150
+
+#define JOG_TIME_BITS 0x03FF
#define N_GUI_EVENT 16
-#define EVENT_BITS 0xE000
-#define EVENT_PRESS 0x8000
-#define EVENT_RELEASE 0x4000
-#define EVENT_HOLD 0xC000
-#define EVENT_JOG 0x2000
+#define EVENT_BITS 0xE000
+#define EVENT_PRESS 0x8000
+#define EVENT_RELEASE 0x4000
+#define EVENT_HOLD 0xC000
+#define EVENT_JOG 0x2000
+#define EVENT_WAS_HOLD 0x1000
#define GUI_INIT 0x00
#define GUI_WAVE 0x01
#define GUI_TITLE_SAVE_N 21
#define GUI_TITLE_SAVE_INSERT 16
+
+#define GET_JOG() ((JOG_A ? JOG_L : 0) ^ (JOG_B ? JOG_H : 0))
+
+
// event handling
inline void add_gui_event(const uint16_t event);
// handling inputs
-inline void int_jog (void) LOWTEXT_INT;
-inline void int_button_abcdef (void) LOWTEXT;
-inline void int_button_y (void) LOWTEXT_INT;
+inline void int_jog (void) LOWTEXT_INT;
+inline void int_jog_timer (void);
+inline uint16_t gui_jog_boost(const uint16_t time);
+inline void int_button_abcdef (void) LOWTEXT;
+inline void int_button_y (void) LOWTEXT_INT;
// general setup