From 8fe8fbee25f127c8cac55f8110ec44dc079f2ff1 Mon Sep 17 00:00:00 2001 From: dekunukem Date: Sun, 9 Jan 2022 16:53:05 +0000 Subject: [PATCH] implemented new custom map format --- user_program/code_mapping.py | 47 ++++++++++++++-- user_program/usb4vc_main.py | 2 +- user_program/usb4vc_ui.py | 77 +++++++++++++------------- user_program/usb4vc_usb_scan.py | 98 +++++++++++++++++++-------------- 4 files changed, 140 insertions(+), 84 deletions(-) diff --git a/user_program/code_mapping.py b/user_program/code_mapping.py index 612d4a5..e7f81a6 100644 --- a/user_program/code_mapping.py +++ b/user_program/code_mapping.py @@ -1,4 +1,4 @@ -code_lookup = { +code_name_to_value_lookup = { 'KEY_RESERVED':(0, 'kb_key'), 'KEY_ESC':(1, 'kb_key'), 'KEY_1':(2, 'kb_key'), @@ -279,6 +279,43 @@ code_lookup = { 'IBM_GGP_JS2_YN':('IBM_GGP_JS2_YN', 'ibm_ggp_half_axis'), } +code_value_to_name_lookup = { + 0x130:'BTN_SOUTH', + 0x131:'BTN_EAST', + 0x132:'BTN_C', + 0x133:'BTN_NORTH', + 0x134:'BTN_WEST', + 0x135:'BTN_Z', + 0x136:'BTN_TL', + 0x137:'BTN_TR', + 0x138:'BTN_TL2', + 0x139:'BTN_TR2', + 0x13a:'BTN_SELECT', + 0x13b:'BTN_START', + 0x13c:'BTN_MODE', + 0x13d:'BTN_THUMBL', + 0x13e:'BTN_THUMBR', + 0x00:'ABS_X', + 0x01:'ABS_Y', + 0x02:'ABS_Z', + 0x03:'ABS_RX', + 0x04:'ABS_RY', + 0x05:'ABS_RZ', + 0x06:'ABS_THROTTLE', + 0x07:'ABS_RUDDER', + 0x08:'ABS_WHEEL', + 0x09:'ABS_GAS', + 0x0a:'ABS_BRAKE', + 0x10:'ABS_HAT0X', + 0x11:'ABS_HAT0Y', + 0x12:'ABS_HAT1X', + 0x13:'ABS_HAT1Y', + 0x14:'ABS_HAT2X', + 0x15:'ABS_HAT2Y', + 0x16:'ABS_HAT3X', + 0x17:'ABS_HAT3Y', +} + board_id_lookup = { 'IBMPC':1, 'ADB':2, @@ -308,10 +345,10 @@ custom_profile_1 = { 'mapping': { # buttons to buttons - 'BTN_X': {'code':'BTN_LEFT'}, - 'BTN_B': {'code':'BTN_RIGHT'}, - 'BTN_Y': {'code':'BTN_MIDDLE'}, - 'BTN_A': {'code':'BTN_MIDDLE'}, + 'BTN_SOUTH': {'code':'BTN_LEFT'}, + 'BTN_EAST': {'code':'BTN_RIGHT'}, + 'BTN_NORTH': {'code':'IBM_GGP_BTN_1'}, + 'BTN_WEST': {'code':'BTN_MIDDLE'}, # analog stick to analog stick 'ABS_X': {'code':'REL_X', 'deadzone_percent':15}, 'ABS_Y': {'code':'REL_Y', 'deadzone_percent':15}, diff --git a/user_program/usb4vc_main.py b/user_program/usb4vc_main.py index 0b768ee..38ebf2b 100644 --- a/user_program/usb4vc_main.py +++ b/user_program/usb4vc_main.py @@ -25,7 +25,7 @@ def reset_pboard(): GPIO.setup(PBOARD_DFU_PIN, GPIO.IN) # GPIO.output(PBOARD_DFU_PIN, GPIO.LOW) -reset_pboard() +# reset_pboard() # use sudo -E to preserve environmental variables for python3 diff --git a/user_program/usb4vc_ui.py b/user_program/usb4vc_ui.py index fa03c4c..cad6242 100644 --- a/user_program/usb4vc_ui.py +++ b/user_program/usb4vc_ui.py @@ -127,28 +127,31 @@ custom_profile_1 = { 'protocol_name':'GAMEPORT_GENERIC_GAMEPAD', 'mapping': { - # buttons to buttons - 'BTN_X': {'code':'BTN_LEFT'}, - 'BTN_B': {'code':'BTN_RIGHT'}, - 'BTN_Y': {'code':'BTN_MIDDLE'}, - 'BTN_A': {'code':'BTN_MIDDLE'}, - # analog stick to analog stick - 'ABS_X': {'code':'REL_X', 'deadzone_percent':15}, - 'ABS_Y': {'code':'REL_Y', 'deadzone_percent':15}, - 'ABS_HAT0X': {'code':'IBM_GGP_JS1_X'}, - 'ABS_HAT0Y': {'code':'IBM_GGP_JS1_Y'}, - # buttons to analog stick + # usb gamepad button to generic gamepad button + 'BTN_NORTH': {'code':'IBM_GGP_BTN_1'}, + 'BTN_WEST': {'code':'IBM_GGP_BTN_2'}, + # usb analog axes to generic gamepad analog axes + 'ABS_X': {'code':'IBM_GGP_JS1_X'}, + 'ABS_Y': {'code':'IBM_GGP_JS1_Y'}, + # usb gamepad button to generic gamepad analog axes 'BTN_TL': {'code':'IBM_GGP_JS1_XN'}, 'BTN_TR': {'code':'IBM_GGP_JS1_XP'}, - # buttons to keyboard key + # usb gamepad button to keyboard key 'BTN_START': {'code':'KEY_A'}, 'BTN_SELECT': {'code':'KEY_B'}, - # analog stick to keyboard key - 'ABS_RX': {'code':'KEY_RIGHT', 'code_neg':'KEY_LEFT', 'deadzone_percent':15}, - 'ABS_RY': {'code':'KEY_DOWN', 'code_neg':'KEY_UP', 'deadzone_percent':15}, + # usb gamepad analog axes to keyboard key + # 'ABS_HAT0X': {'code':'KEY_RIGHT', 'code_neg':'KEY_LEFT', 'deadzone_percent':15}, + # 'ABS_HAT0Y': {'code':'KEY_DOWN', 'code_neg':'KEY_UP', 'deadzone_percent':15}, + 'ABS_HAT0X': {'code':'KEY_1', 'code_neg':'KEY_2', 'deadzone_percent':15}, + 'ABS_HAT0Y': {'code':'KEY_3', 'code_neg':'KEY_4', 'deadzone_percent':15}, + # usb gamepad button to mouse buttons + 'BTN_SOUTH': {'code':'BTN_LEFT'}, + 'BTN_EAST': {'code':'BTN_RIGHT'}, + # usb gamepad analog axes to mouse axes + 'ABS_Z': {'code':'REL_X', 'deadzone_percent':15}, + 'ABS_RZ': {'code':'REL_Y', 'deadzone_percent':15}, } } - custom_profile_list = [custom_profile_1] """ @@ -332,17 +335,17 @@ class usb4vc_menu(object): self.current_page = 0 self.level_size = 5 self.page_size = [4, 5, 4, 1, 1] - self.kb_opts = list(pboard['protocol_list_keyboard']) - self.mouse_opts = list(pboard['protocol_list_mouse']) - self.gamepad_opts = list(pboard['protocol_list_gamepad']) + self.kb_protocol_list = list(pboard['protocol_list_keyboard']) + self.mouse_protocol_list = list(pboard['protocol_list_mouse']) + self.gamepad_protocol_list = list(pboard['protocol_list_gamepad']) self.pb_info = dict(pboard) - self.current_keyboard_protocol_index = self.cap_index(conf_dict['keyboard_protocol_index'], len(self.kb_opts)) - self.current_mouse_protocol_index = self.cap_index(conf_dict["mouse_protocol_index"], len(self.mouse_opts)) + self.current_keyboard_protocol_index = self.cap_index(conf_dict['keyboard_protocol_index'], len(self.kb_protocol_list)) + self.current_mouse_protocol_index = self.cap_index(conf_dict["mouse_protocol_index"], len(self.mouse_protocol_list)) self.current_mouse_sensitivity_offset_index = self.cap_index(conf_dict["mouse_sensitivity_index"], len(mouse_sensitivity_list)) - self.current_gamepad_protocol_index = self.cap_index(conf_dict["gamepad_protocol_index"], len(self.gamepad_opts)) - self.current_keyboard_protocol = self.kb_opts[self.current_keyboard_protocol_index] - self.current_mouse_protocol = self.mouse_opts[self.current_mouse_protocol_index] - self.current_gamepad_protocol = self.gamepad_opts[self.current_gamepad_protocol_index] + self.current_gamepad_protocol_index = self.cap_index(conf_dict["gamepad_protocol_index"], len(self.gamepad_protocol_list)) + self.current_keyboard_protocol = self.kb_protocol_list[self.current_keyboard_protocol_index] + self.current_mouse_protocol = self.mouse_protocol_list[self.current_mouse_protocol_index] + self.current_gamepad_protocol = self.gamepad_protocol_list[self.current_gamepad_protocol_index] self.last_spi_message = [] self.bluetooth_device_list = None self.error_message = '' @@ -393,15 +396,15 @@ class usb4vc_menu(object): if page == 0: with canvas(oled_device) as draw: oled_print_centered("Keyboard Protocol", font_medium, 0, draw) - oled_print_centered(self.kb_opts[self.current_keyboard_protocol_index]['display_name'], font_medium, 15, draw) + oled_print_centered(self.kb_protocol_list[self.current_keyboard_protocol_index]['display_name'], font_medium, 15, draw) if page == 1: with canvas(oled_device) as draw: oled_print_centered("Mouse Protocol", font_medium, 0, draw) - oled_print_centered(self.mouse_opts[self.current_mouse_protocol_index]['display_name'], font_medium, 15, draw) + oled_print_centered(self.mouse_protocol_list[self.current_mouse_protocol_index]['display_name'], font_medium, 15, draw) if page == 2: with canvas(oled_device) as draw: oled_print_centered("Gamepad Protocol", font_medium, 0, draw) - oled_print_centered(self.gamepad_opts[self.current_gamepad_protocol_index]['display_name'], font_medium, 15, draw) + oled_print_centered(self.gamepad_protocol_list[self.current_gamepad_protocol_index]['display_name'], font_medium, 15, draw) if page == 3: with canvas(oled_device) as draw: oled_print_centered("Mouse Sensitivity", font_medium, 0, draw) @@ -466,21 +469,21 @@ class usb4vc_menu(object): def send_protocol_set_spi_msg(self): status_dict = {} - for index, item in enumerate(self.kb_opts): + for index, item in enumerate(self.kb_protocol_list): if item['pid'] & 0x7f in status_dict and status_dict[item['pid'] & 0x7f] == 1: continue status_dict[item['pid'] & 0x7f] = 0 if index == self.current_keyboard_protocol_index: status_dict[item['pid'] & 0x7f] = 1 - for index, item in enumerate(self.mouse_opts): + for index, item in enumerate(self.mouse_protocol_list): if item['pid'] & 0x7f in status_dict and status_dict[item['pid'] & 0x7f] == 1: continue status_dict[item['pid'] & 0x7f] = 0 if index == self.current_mouse_protocol_index: status_dict[item['pid'] & 0x7f] = 1 - for index, item in enumerate(self.gamepad_opts): + for index, item in enumerate(self.gamepad_protocol_list): if item['pid'] & 0x7f in status_dict and status_dict[item['pid'] & 0x7f] == 1: continue status_dict[item['pid'] & 0x7f] = 0 @@ -499,9 +502,9 @@ class usb4vc_menu(object): this_msg = list(usb4vc_shared.set_protocl_spi_msg_template) this_msg[3:3+len(protocol_bytes)] = protocol_bytes - self.current_keyboard_protocol = self.kb_opts[self.current_keyboard_protocol_index] - self.current_mouse_protocol = self.mouse_opts[self.current_mouse_protocol_index] - self.current_gamepad_protocol = self.gamepad_opts[self.current_gamepad_protocol_index] + self.current_keyboard_protocol = self.kb_protocol_list[self.current_keyboard_protocol_index] + self.current_mouse_protocol = self.mouse_protocol_list[self.current_mouse_protocol_index] + self.current_gamepad_protocol = self.gamepad_protocol_list[self.current_gamepad_protocol_index] # print('this', this_msg) # print('last', self.last_spi_message) @@ -525,11 +528,11 @@ class usb4vc_menu(object): self.goto_level(1) if level == 1: if page == 0: - self.current_keyboard_protocol_index = (self.current_keyboard_protocol_index + 1) % len(self.kb_opts) + self.current_keyboard_protocol_index = (self.current_keyboard_protocol_index + 1) % len(self.kb_protocol_list) if page == 1: - self.current_mouse_protocol_index = (self.current_mouse_protocol_index + 1) % len(self.mouse_opts) + self.current_mouse_protocol_index = (self.current_mouse_protocol_index + 1) % len(self.mouse_protocol_list) if page == 2: - self.current_gamepad_protocol_index = (self.current_gamepad_protocol_index + 1) % len(self.gamepad_opts) + self.current_gamepad_protocol_index = (self.current_gamepad_protocol_index + 1) % len(self.gamepad_protocol_list) if page == 3: self.current_mouse_sensitivity_offset_index = (self.current_mouse_sensitivity_offset_index + 1) % len(mouse_sensitivity_list) if page == 4: diff --git a/user_program/usb4vc_usb_scan.py b/user_program/usb4vc_usb_scan.py index eb5f3a2..cdcc94b 100644 --- a/user_program/usb4vc_usb_scan.py +++ b/user_program/usb4vc_usb_scan.py @@ -7,6 +7,8 @@ import threading import RPi.GPIO as GPIO import usb4vc_ui import usb4vc_shared +import code_mapping + """ sudo apt install stm32flash @@ -110,7 +112,7 @@ ABS_HAT1X = 0x12 ABS_HAT1Y = 0x13 ABS_HAT2X = 0x14 ABS_HAT2Y = 0x15 -ABS_HAT3Y = 0x16 +ABS_HAT3X = 0x16 ABS_HAT3Y = 0x17 BTN_LEFT = 0x110 @@ -174,14 +176,14 @@ def convert_to_8bit_midpoint127(value, axes_dict, axis_key): return int((value / rmax) * 255) + 127 IBMPC_GGP_SPI_LOOKUP = { - 'IBMGBTN_1':4, - 'IBMGBTN_2':5, - 'IBMGBTN_3':6, - 'IBMGBTN_4':7, - 'IBMGGP_JS1_X':8, - 'IBMGGP_JS1_Y':9, - 'IBMGGP_JS2_X':10, - 'IBMGGP_JS2_Y':11, + 'IBM_GGP_BTN_1':4, + 'IBM_GGP_BTN_2':5, + 'IBM_GGP_BTN_3':6, + 'IBM_GGP_BTN_4':7, + 'IBM_GGP_JS1_X':8, + 'IBM_GGP_JS1_Y':9, + 'IBM_GGP_JS2_X':10, + 'IBM_GGP_JS2_Y':11, } MOUSE_SPI_LOOKUP = { @@ -195,16 +197,30 @@ MOUSE_SPI_LOOKUP = { REL_WHEEL:8, } -def find_keycode_in_mapping(key_code, mapping_dict): - code_type = None - if ABS_X <= key_code <= ABS_HAT3Y: - code_type = 'usb_gp_axes' - elif BTN_SOUTH <= key_code <= BTN_THUMBR: - code_type = 'usb_gp_btn' - result = mapping_dict.get(key_code) - if code_type is None or result is None: +def find_keycode_in_mapping(source_code, mapping_dict): + source_name = code_mapping.code_value_to_name_lookup.get(source_code) + if source_name is None: return None, None - return code_type, result + target_info = mapping_dict.get(source_name) + if target_info is None or 'code' not in target_info: + return None, None + target_info = dict(target_info) # make a copy so the lookup table itself won't get modified + lookup_result = code_mapping.code_name_to_value_lookup.get(target_info['code']) + if lookup_result is None: + return None, None + source_type = None + if ABS_X <= source_code <= ABS_HAT3Y: + source_type = 'usb_gp_axes' + elif BTN_SOUTH <= source_code <= BTN_THUMBR: + source_type = 'usb_gp_btn' + if source_type is None: + return None, None + target_info['code'] = lookup_result[0] + if 'code_neg' in target_info: + target_info['code_neg'] = code_mapping.code_name_to_value_lookup.get(target_info['code_neg'])[0] + target_info['type'] = lookup_result[1] + # print(source_name, source_type, target_info) + return source_type, target_info def find_furthest_from_midpoint(this_set): curr_best = None @@ -225,14 +241,14 @@ def make_generic_gamepad_spi_packet(gp_status_dict, gp_id, axes_info, mapping_in global curr_mouse_output this_gp_dict = gp_status_dict[gp_id] curr_gp_output = { - 'IBMPC_GBTN_1':set([0]), - 'IBMPC_GBTN_2':set([0]), - 'IBMPC_GBTN_3':set([0]), - 'IBMPC_GBTN_4':set([0]), - 'IBMPC_GGP_JS1_X':set([127]), - 'IBMPC_GGP_JS1_Y':set([127]), - 'IBMPC_GGP_JS2_X':set([127]), - 'IBMPC_GGP_JS2_Y':set([127]), + 'IBM_GGP_BTN_1':set([0]), + 'IBM_GGP_BTN_2':set([0]), + 'IBM_GGP_BTN_3':set([0]), + 'IBM_GGP_BTN_4':set([0]), + 'IBM_GGP_JS1_X':set([127]), + 'IBM_GGP_JS1_Y':set([127]), + 'IBM_GGP_JS2_X':set([127]), + 'IBM_GGP_JS2_Y':set([127]), } curr_kb_output = {} curr_mouse_output = { @@ -254,26 +270,26 @@ def make_generic_gamepad_spi_packet(gp_status_dict, gp_id, axes_info, mapping_in target_code = target_info['code'] target_type = target_info['type'] - # button to button - if source_type == 'usb_gp_btn' and target_type == 'pb_gp_btn' and target_code in curr_gp_output: + # usb gamepad button to generic gamepad button + if source_type == 'usb_gp_btn' and target_type == 'ibm_ggp_btn' and target_code in curr_gp_output: curr_gp_output[target_code].add(this_gp_dict[source_code]) - # analog to analog - if source_type == 'usb_gp_axes' and target_type == 'pb_gp_axes' and target_code in curr_gp_output: + # usb gamepad analog axes to generic gamepad analog axes + if source_type == 'usb_gp_axes' and target_type == 'ibm_ggp_axis' and target_code in curr_gp_output: curr_gp_output[target_code].add(convert_to_8bit_midpoint127(this_gp_dict[source_code], axes_info, source_code)) - # button to analog - if source_type == 'usb_gp_btn' and target_type == 'pb_gp_half_axes' and target_code[:-1] in curr_gp_output and this_gp_dict[source_code]: + # usb gamepad button to generic gamepad analog axes + if source_type == 'usb_gp_btn' and target_type == 'ibm_ggp_half_axis' and target_code[:-1] in curr_gp_output and this_gp_dict[source_code]: if target_code.endswith('P'): axis_value = 255 elif target_code.endswith('N'): axis_value = 0 curr_gp_output[target_code[:-1]].add(axis_value) - # button to keyboard key - if source_type == 'usb_gp_btn' and target_type == 'pb_kb': + # usb gamepad button to keyboard key + if source_type == 'usb_gp_btn' and target_type == 'kb_key': if target_code not in curr_kb_output: curr_kb_output[target_code] = set() curr_kb_output[target_code].add(this_gp_dict[source_code]) - # analog to keyboard key - if source_type == 'usb_gp_axes' and target_type == 'pb_kb': + # usb gamepad analog axes to keyboard key + if source_type == 'usb_gp_axes' and target_type == 'kb_key': if target_code not in curr_kb_output: curr_kb_output[target_code] = set() is_activated = 0 @@ -288,12 +304,12 @@ def make_generic_gamepad_spi_packet(gp_status_dict, gp_id, axes_info, mapping_in if convert_to_8bit_midpoint127(this_gp_dict[source_code], axes_info, source_code) < 127 - deadzone_amount: is_activated = 1 curr_kb_output[target_info['code_neg']].add(is_activated) - # button to mouse buttons + # usb gamepad button to mouse buttons if source_type == 'usb_gp_btn' and target_type == 'mouse_btn' and target_code in curr_mouse_output: curr_mouse_output[target_code].add(this_gp_dict[source_code]) curr_mouse_output['is_modified'] = True - # analog to mouse axes - if source_type == 'usb_gp_axes' and target_type == 'mouse_axes' and target_code in curr_mouse_output: + # usb gamepad analog axes to mouse axes + if source_type == 'usb_gp_axes' and target_type == 'usb_rel_axis' and target_code in curr_mouse_output: movement = convert_to_8bit_midpoint127(this_gp_dict[source_code], axes_info, source_code) - 127 deadzone_amount = int(127 * target_info['deadzone_percent'] / 100) if abs(movement) <= deadzone_amount: @@ -319,12 +335,12 @@ def make_generic_gamepad_spi_packet(gp_status_dict, gp_id, axes_info, mapping_in gp_spi_msg = list(gamepad_event_ibm_ggp_spi_msg_template) gp_spi_msg[3] = gp_id; for key in curr_gp_output: - if "IBMGBTN_" in key: + if "IBM_GGP_BTN_" in key: this_value = 0 if 1 in curr_gp_output[key]: this_value = 1 gp_spi_msg[IBMPC_GGP_SPI_LOOKUP[key]] = this_value - if 'IBMGGP_JS' in key: + if 'IBM_GGP_JS1' in key: if key in prev_gp_output: new_value_set = curr_gp_output[key] - prev_gp_output[key] if len(new_value_set) > 0: