kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Merge remote-tracking branch 'upstream/dev' into dev
commit
f804699413
212
src/osd.c
212
src/osd.c
|
@ -30,19 +30,40 @@
|
|||
|
||||
#define MAX_MENU_DEPTH 4
|
||||
|
||||
// =============================================================
|
||||
// Definitions for the key press interface
|
||||
// =============================================================
|
||||
|
||||
#define LONG_KEY_PRESS_DURATION 25
|
||||
|
||||
// =============================================================
|
||||
// Main states that the OSD can be in
|
||||
// =============================================================
|
||||
|
||||
typedef enum {
|
||||
IDLE, // No menu
|
||||
CAPTURE, // Screen capture button was pressed
|
||||
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;
|
||||
|
||||
// =============================================================
|
||||
|
@ -512,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;
|
||||
|
@ -528,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;
|
||||
|
@ -1022,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;
|
||||
|
@ -1431,8 +1476,6 @@ void osd_update_palette() {
|
|||
|
||||
}
|
||||
|
||||
// Flush the previous swapBuffer() response from the GPU->ARM mailbox
|
||||
RPI_Mailbox0Flush( MB0_TAGS_ARM_TO_VC );
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag(TAG_SET_PALETTE, num_colours, palette_data);
|
||||
RPI_PropertyProcess();
|
||||
|
@ -1633,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");
|
||||
|
@ -1815,7 +1865,7 @@ int osd_active() {
|
|||
void osd_refresh() {
|
||||
|
||||
if (osd_state == MENU || osd_state == PARAM || osd_state == INFO) {
|
||||
osd_clear_no_palette();
|
||||
osd_clear_no_palette();
|
||||
redraw_menu();
|
||||
} else {
|
||||
osd_clear();
|
||||
|
@ -1831,41 +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_cal) {
|
||||
|
||||
// TODO: A long press should run the HDMI Calibration
|
||||
|
||||
// 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 (key == key_capture) {
|
||||
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 CAL
|
||||
osd_state = CAPTURE;
|
||||
} else if (key == OSD_EXPIRED) {
|
||||
osd_clear();
|
||||
// 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
|
||||
|
@ -1874,7 +1948,7 @@ int osd_key(int key) {
|
|||
osd_state = IDLE;
|
||||
break;
|
||||
|
||||
case CLOCK_CAL:
|
||||
case A2_CLOCK_CAL:
|
||||
// HDMI Calibration
|
||||
clear_menu_bits();
|
||||
osd_set(0, ATTR_DOUBLE_SIZE, "HDMI Calibration");
|
||||
|
@ -1892,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;
|
||||
|
@ -2069,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;
|
||||
}
|
||||
|
|
|
@ -420,7 +420,6 @@ static int calibrate_sampling_clock() {
|
|||
a = a * 13;
|
||||
}
|
||||
// Switch to new core clock speed
|
||||
RPI_Mailbox0Flush(MB0_TAGS_ARM_TO_VC);
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag(TAG_SET_CLOCK_RATE, CORE_CLK_ID, core_freq, 1);
|
||||
RPI_PropertyProcess();
|
||||
|
@ -1396,9 +1395,6 @@ int total_N_frames(capture_info_t *capinfo, int n, int mode7, int elk) {
|
|||
|
||||
#ifdef MULTI_BUFFER
|
||||
void swapBuffer(int buffer) {
|
||||
// Flush the previous response from the GPU->ARM mailbox
|
||||
// Doing it like this avoids stalling for the response
|
||||
RPI_Mailbox0Flush(MB0_TAGS_ARM_TO_VC);
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag(TAG_SET_VIRTUAL_OFFSET, 0, capinfo->height * buffer);
|
||||
// Use version that doesn't wait for the response
|
||||
|
|
|
@ -16,9 +16,17 @@ static int pt_index ;
|
|||
|
||||
//#define PRINT_PROP_DEBUG 1
|
||||
|
||||
static volatile int mb_response_pending = 0;
|
||||
|
||||
void RPI_PropertyInit( void )
|
||||
{
|
||||
|
||||
// Process any pending responses from the previous call
|
||||
if (mb_response_pending) {
|
||||
RPI_Mailbox0Read( MB0_TAGS_ARM_TO_VC );
|
||||
mb_response_pending = 0;
|
||||
}
|
||||
|
||||
/* Without this, we end up reading garbage back in the property interface version of init_framebuffer */
|
||||
/* TODO: investigate what's going on here! */
|
||||
/* Values < 32 fail in this way */
|
||||
|
@ -262,6 +270,9 @@ void RPI_PropertyProcessNoCheck( void )
|
|||
log_info( "Request: %3d %8.8X", i, pt[i] );
|
||||
#endif
|
||||
RPI_Mailbox0Write( MB0_TAGS_ARM_TO_VC, (unsigned int)pt );
|
||||
|
||||
// Remember that we have a response pending
|
||||
mb_response_pending = 1;
|
||||
}
|
||||
|
||||
rpi_mailbox_property_t* RPI_PropertyGet( rpi_mailbox_tag_t tag)
|
||||
|
|
|
@ -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