Pi Firmware: Implemented configurable button actions (#66)

Change-Id: I141c697354a286cebb695f9d0b15f5552478291f
pull/101/head^2
David Banks 2019-04-26 17:40:59 +01:00
rodzic 3e6d66c996
commit 51a445fdf7
3 zmienionych plików z 178 dodań i 73 usunięć

228
src/osd.c
Wyświetl plik

@ -41,15 +41,29 @@
// =============================================================
typedef enum {
IDLE, // No menu
CAPTURE, // Screen capture button was pressed
CAL, // Wait for cal button to be released
CLOCK_CAL , // Intermediate state in clock calibration
CLOCK_CAL0, // Intermediate state in clock calibration
CLOCK_CAL1, // Intermediate state in clock calibration
MENU, // Browsing a menu
PARAM, // Changing the value of a menu item
INFO // Viewing an info panel
IDLE, // Wait for button to be pressed
DURATION, // Determine whether short or long button press
MIN_ACTION, // Marker state, never actually used
// The next N states are the pre-defined action states
// At most 6 of these can be bound to button presses (3 buttons, long/short)
A0_LAUNCH, // Action 0: Launch menu system
A1_CAPTURE, // Action 1: Screen capture
A2_CLOCK_CAL, // Action 2: HDMI clock calibration
A3_AUTO_CAL, // Action 3: Auto calibration
A4_SCANLINES, // Action 4: Toggle scanlines
A5_SPARE, // Action 5: Spare
A6_SPARE, // Action 6: Spare
A7_SPARE, // Action 7: Spare
MAX_ACTION, // Marker state, never actually used
CLOCK_CAL0, // Intermediate state in clock calibration
CLOCK_CAL1, // Intermediate state in clock calibration
MENU, // Browsing a menu
PARAM, // Changing the value of a menu item
INFO // Viewing an info panel
} osd_state_t;
// =============================================================
@ -519,7 +533,7 @@ static char message[80];
static int active = 0;
// Main state of the OSD
osd_state_t osd_state;
osd_state_t osd_state = IDLE;
// Current menu depth
static int depth = 0;
@ -535,14 +549,24 @@ static int palette = PALETTE_RGB;
// Currently selected input mux setting
static int mux = 0;
// Keymap
// Default action map, maps from physical key press to action
static osd_state_t action_map[] = {
A0_LAUNCH, // 0 - SW1 short press
A1_CAPTURE, // 1 - SW2 short press
A2_CLOCK_CAL, // 2 - SW3 short press
A4_SCANLINES, // 3 - SW1 long press
A5_SPARE, // 4 - SW2 long press
A3_AUTO_CAL, // 5 - SW3 long press
};
#define NUM_ACTIONS (sizeof(action_map) / sizeof(osd_state_t))
// Default keymap, used for menu navigation
static int key_enter = OSD_SW1;
static int key_menu_up = OSD_SW2;
static int key_menu_down = OSD_SW3;
static int key_value_dec = OSD_SW2;
static int key_value_inc = OSD_SW3;
static int key_cal = OSD_SW3;
static int key_capture = OSD_SW2;
// Whether the menu back pointer is at the start (0) or end (1) of the menu
static int return_at_end = 1;
@ -1029,6 +1053,20 @@ static int get_key_down_duration(int key) {
return 0;
}
static void set_key_down_duration(int key, int value) {
switch (key) {
case OSD_SW1:
sw1counter = value;
break;
case OSD_SW2:
sw2counter = value;
break;
case OSD_SW3:
sw3counter = value;
break;
}
}
void yuv2rgb(int colour, int luma_scale, int black_ref, int y1_millivolts, int u1_millivolts, int v1_millivolts, int *r, int *g, int *b) {
static int green_chroma_scale = 100;
int chroma_scale;
@ -1638,17 +1676,24 @@ void process_single_profile(char *buffer) {
case 4:
key_value_inc = val;
break;
case 5:
key_cal = val;
break;
case 6:
key_capture = val;
break;
}
}
i++;
}
}
prop = get_prop(buffer, "actionmap");
if (prop) {
int i = 0;
while (*prop && i < NUM_ACTIONS) {
osd_state_t val = MIN_ACTION + 1 + ((*prop++) - '0');
if (val > MIN_ACTION && val < MAX_ACTION) {
action_map[i] = val;
}
i++;
}
}
// Implement a return property that selects whether the menu
// return links is placed at the start (0) or end (1).
prop = get_prop(buffer, "return");
@ -1836,34 +1881,65 @@ int osd_key(int key) {
int ret = -1;
static int cal_count;
static int last_vsync;
static int last_key;
switch (osd_state) {
case IDLE:
if (key == key_enter) {
// Enter
osd_state = MENU;
current_menu[depth] = &main_menu;
current_item[depth] = 0;
if(active == 0) {
clear_menu_bits();
}
redraw_menu();
} else if (key == key_capture) {
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// come back to CAPTURE
osd_state = CAPTURE;
} else if (key == key_cal) {
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// come back to CAL
osd_state = CAL;
} else if (key == OSD_EXPIRED) {
if (key == OSD_EXPIRED) {
osd_clear();
// Remain in the idle state
} else {
// Remember the original key pressed
last_key = key;
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// come back to DURATION
osd_state = DURATION;
}
break;
case CAPTURE:
case DURATION:
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// Use duration to determine action
val = get_key_down_duration(last_key);
// Descriminate between short and long button press as early as possible
if (val == 0 || val > LONG_KEY_PRESS_DURATION) {
// Calculate the logical key pressed (0..5) based on the physical key and the duration
int key_pressed = (last_key - OSD_SW1);
if (val) {
// long press
key_pressed += 3;
// avoid key immediately auto-repeating
set_key_down_duration(last_key, 0);
}
log_info("Key pressed = %d", key_pressed);
if (key_pressed < 0 || key_pressed >= NUM_ACTIONS) {
log_warn("Key pressed (%d) out of range 0..%d ", key_pressed, NUM_ACTIONS - 1);
osd_state = IDLE;
} else {
log_info("Key pressed = %d", key_pressed);
int action = action_map[key_pressed];
log_info("Action = %d", action);
// Transition to action state
osd_state = action;
}
}
break;
case A0_LAUNCH:
osd_state = MENU;
current_menu[depth] = &main_menu;
current_item[depth] = 0;
if(active == 0) {
clear_menu_bits();
}
redraw_menu();
break;
case A1_CAPTURE:
// Capture screen shot
capture_screenshot(capinfo, profile_names[get_feature(F_PROFILE)]);
// Fire OSD_EXPIRED in 1 frames time
@ -1872,34 +1948,10 @@ int osd_key(int key) {
osd_state = IDLE;
break;
case CAL:
// Cal butto pressed, use duration to determine action
val = get_key_down_duration(key_cal);
if (val > LONG_KEY_PRESS_DURATION) {
// Auto Calibration
clear_menu_bits();
osd_set(0, ATTR_DOUBLE_SIZE, "Auto Calibration");
action_calibrate_auto();
// Fire OSD_EXPIRED in 50 frames time
ret = 50;
// come back to IDLE
osd_state = IDLE;
} else if (val == 0) {
// HDMI Calibration
clear_menu_bits();
osd_set(0, ATTR_DOUBLE_SIZE, "HDMI Calibration");
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// come back to CLOCK_CAL
osd_state = CLOCK_CAL;
} else {
// Fire OSD_EXPIRED in 1 frames time
ret = 1;
// come back to CAL
}
break;
case CLOCK_CAL:
case A2_CLOCK_CAL:
// HDMI Calibration
clear_menu_bits();
osd_set(0, ATTR_DOUBLE_SIZE, "HDMI Calibration");
// Record the starting value of vsync
last_vsync = get_vsync();
// Enable vsync
@ -1914,6 +1966,42 @@ int osd_key(int key) {
osd_state = CLOCK_CAL0;
break;
case A3_AUTO_CAL:
clear_menu_bits();
osd_set(0, ATTR_DOUBLE_SIZE, "Auto Calibration");
action_calibrate_auto();
// Fire OSD_EXPIRED in 50 frames time
ret = 50;
// come back to IDLE
osd_state = IDLE;
break;
case A4_SCANLINES:
clear_menu_bits();
set_scanlines(1 - get_scanlines());
if (get_scanlines()) {
osd_set(0, ATTR_DOUBLE_SIZE, "Scanlines on");
} else {
osd_set(0, ATTR_DOUBLE_SIZE, "Scanlines off");
}
// Fire OSD_EXPIRED in 50 frames time
ret = 50;
// come back to IDLE
osd_state = IDLE;
break;
case A5_SPARE:
case A6_SPARE:
case A7_SPARE:
clear_menu_bits();
sprintf(message, "Action %d (spare)", osd_state - (MIN_ACTION + 1));
osd_set(0, ATTR_DOUBLE_SIZE, message);
// Fire OSD_EXPIRED in 50 frames time
ret = 50;
// come back to IDLE
osd_state = IDLE;
break;
case CLOCK_CAL0:
// Fire OSD_EXPIRED in 50 frames time
ret = 50;
@ -2091,6 +2179,10 @@ int osd_key(int key) {
redraw_menu();
}
break;
default:
log_warn("Illegal osd state %d reached", osd_state);
osd_state = IDLE;
}
return ret;
}

Wyświetl plik

@ -22,5 +22,6 @@ genlock_adjust=0
num_buffers=0
debug=0
input_mux=0
keymap=132323
keymap=13232
actionmap=012453
return=0

Wyświetl plik

@ -185,16 +185,28 @@
# - 1 is switching between modes0-6 and mode 7 on BBC micro / Master 128 or Electron with a Mode 7 expansion board
# - 2 is switching between PC CGA and EGA modes
#
# keymap: specifies which keys invoke which actions
# - The default is 1232332
#
# actionmap: specifies how keys presses are bound to actions
# - The default is 012453
# - The format is <SW1 short><SW2 short><SW3 short><SW1 long><SW2 long><SW3 long>
# - The values of the digits indicate the action:
# - 0 = Launch Menu
# - 1 = Screen Capture
# - 2 = HDMI Clock Calibration
# - 3 = Auto Calibration
# - 4 = Toggle Scanlines
# - 5 = Spare
# - 6 = Spare
# - 7 = Spare
#
# keymap: specifies how keys are used for menu navigation
# - The default is 12323
# - The individual digits numbers correspond to the following actions:
# - key_enter
# - key_menu_up
# - key_menu_down
# - key_value_dec
# - key_value_inc
# - key_cal
# - key_capture
# - Key SW1 is 1, key SW2 is 2, etc
#
# return: specifies the position of the return link in menus