kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Pi Firmware: Implemented configurable button actions (#66)
Change-Id: I141c697354a286cebb695f9d0b15f5552478291fpull/101/head^2
rodzic
3e6d66c996
commit
51a445fdf7
228
src/osd.c
228
src/osd.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -22,5 +22,6 @@ genlock_adjust=0
|
|||
num_buffers=0
|
||||
debug=0
|
||||
input_mux=0
|
||||
keymap=132323
|
||||
keymap=13232
|
||||
actionmap=012453
|
||||
return=0
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue