Updated with source code
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -51,3 +51,6 @@ components.x/
|
||||
components/
|
||||
main/main.cpp.bak2
|
||||
webfs/
|
||||
webserver/font-awesome/fonts/fontawesome-webfont.ttf.orig
|
||||
webserver/font-awesome/fonts/fontawesome-webfont.woff.orig
|
||||
|
||||
|
||||
@@ -12,4 +12,5 @@ hosts.
|
||||
|
||||
Please see my website, https://eaw.app for more documentation and recent updates.
|
||||
|
||||
The firmware is undergoing rapid advances and will initially only be included as releases.
|
||||
The source code for the mz25key is identical to the SharpKey, just the build time configuration via the KConfig menu. The provided sdkconfig
|
||||
is setup so that the source code will build the mz25key.
|
||||
|
||||
10594
docs/OMOTON_K8508.pdf
Normal file
10594
docs/OMOTON_K8508.pdf
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/PERIBOARD-810.pdf
Normal file
BIN
docs/PERIBOARD-810.pdf
Normal file
Binary file not shown.
BIN
docs/PERIBOARD-810_Intl.pdf
Normal file
BIN
docs/PERIBOARD-810_Intl.pdf
Normal file
Binary file not shown.
BIN
docs/PS2_Mouse.pdf
Normal file
BIN
docs/PS2_Mouse.pdf
Normal file
Binary file not shown.
BIN
docs/Sanwa_SKB-L1_Keyboard.pdf
Normal file
BIN
docs/Sanwa_SKB-L1_Keyboard.pdf
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/BT.cpp
|
||||
788
main/BT.cpp
Normal file
788
main/BT.cpp
Normal file
@@ -0,0 +1,788 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: BT.cpp
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Bluetooth base class.
|
||||
// This source file contains the class to encapsulate the Bluetooth ESP API. Both
|
||||
// BLE and BT Classic are supported. Allows for scanning, pairing and connection
|
||||
// to a peripheral device such as a Keyboard or Mouse.
|
||||
//
|
||||
// The application uses the Espressif Development environment with Arduino components.
|
||||
// This is necessary as the class uses the Arduino methods for GPIO manipulation. I
|
||||
// was considering using pure Espressif IDF methods but considered the potential
|
||||
// of also using this class on an Arduino project.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_spp_api.h"
|
||||
#include "Arduino.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "BT.h"
|
||||
|
||||
#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(*a))
|
||||
|
||||
// Out of object pointer to a singleton class for use in the ESP IDF API callback routines which werent written for C++. Other methods can be used but this one is the simplest
|
||||
// to understand and the class can only ever be singleton.
|
||||
BT *pBTThis = NULL;
|
||||
|
||||
// Method to locate a valid scan entry in the results list.
|
||||
//
|
||||
BT::t_scanListItem* BT::findValidScannedDevice(esp_bd_addr_t bda, std::vector<t_scanListItem> &scanList)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
|
||||
// Loop through the scan results list looking for a valid entry, return entry if found.
|
||||
for(std::size_t idx = 0; idx < scanList.size(); idx++)
|
||||
{
|
||||
if (memcmp(bda, scanList[idx].bda, sizeof(esp_bd_addr_t)) == 0)
|
||||
{
|
||||
return &scanList[idx];
|
||||
}
|
||||
}
|
||||
return(nullptr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Method to add a valid BT Classic device onto the scan list.
|
||||
//
|
||||
void BT::addBTScanDevice(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid_t *uuid, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
// Locals.
|
||||
t_scanListItem item;
|
||||
|
||||
// Find a valid device in the BT Classic scan results. If a device is found then this callback is with new data.
|
||||
t_scanListItem* result = findValidScannedDevice(bda, btCtrl.btScanList);
|
||||
if(result)
|
||||
{
|
||||
// Information can be updated through several calls.
|
||||
if(result->name.length() == 0 && name && name_len)
|
||||
{
|
||||
result->name.assign((char *)name, name_len);
|
||||
}
|
||||
if(result->bt.uuid.len == 0 && uuid->len)
|
||||
{
|
||||
memcpy(&result->bt.uuid, uuid, sizeof(esp_bt_uuid_t));
|
||||
}
|
||||
if(rssi != 0)
|
||||
{
|
||||
result->rssi = rssi;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate new list item with device results.
|
||||
item.transport = ESP_HID_TRANSPORT_BT;
|
||||
memcpy(item.bda, bda, sizeof(esp_bd_addr_t));
|
||||
memcpy(&item.bt.cod, cod, sizeof(esp_bt_cod_t));
|
||||
memcpy(&item.bt.uuid, uuid, sizeof(esp_bt_uuid_t));
|
||||
item.usage = esp_hid_usage_from_cod((uint32_t)cod);
|
||||
item.rssi = rssi;
|
||||
item.name = "";
|
||||
|
||||
// Store device name if present. This is possibly provided in a seperate callback.
|
||||
if(name_len && name)
|
||||
{
|
||||
item.name.assign((char *)name, name_len);
|
||||
}
|
||||
|
||||
// Add new item onto list.
|
||||
btCtrl.btScanList.push_back(item);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Method to add a valid BLE device to our scan list.
|
||||
//
|
||||
void BT::addBLEScanDevice(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type, uint16_t appearance, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
t_scanListItem item;
|
||||
|
||||
// See if the device is already in the list, exit if found as data updates with seperate callbacks not normal under BLE.
|
||||
if(findValidScannedDevice(bda, btCtrl.bleScanList))
|
||||
{
|
||||
ESP_LOGW(TAG, "Result already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate the item with data.
|
||||
item.transport = ESP_HID_TRANSPORT_BLE;
|
||||
memcpy(item.bda, bda, sizeof(esp_bd_addr_t));
|
||||
item.ble.appearance = appearance;
|
||||
item.ble.addr_type = addr_type;
|
||||
item.usage = esp_hid_usage_from_appearance(appearance);
|
||||
item.rssi = rssi;
|
||||
item.name = "";
|
||||
|
||||
// Store device name if present.
|
||||
if(name_len && name)
|
||||
{
|
||||
item.name.assign((char *)name, name_len);
|
||||
}
|
||||
|
||||
// Add new item onto list.
|
||||
btCtrl.bleScanList.push_back(item);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Method to process a device data resulting from a BT scan.
|
||||
//
|
||||
void BT::processBTDeviceScanResult(esp_bt_gap_cb_param_t * param)
|
||||
{
|
||||
// Locals
|
||||
//
|
||||
uint32_t codv = 0;
|
||||
esp_bt_cod_t *cod = (esp_bt_cod_t *)&codv;
|
||||
int8_t rssi = 0;
|
||||
uint8_t *name = nullptr;
|
||||
uint8_t name_len = 0;
|
||||
esp_bt_uuid_t uuid;
|
||||
uint8_t len = 0;
|
||||
uint8_t *data = 0;
|
||||
|
||||
uuid.len = ESP_UUID_LEN_16;
|
||||
uuid.uuid.uuid16 = 0;
|
||||
|
||||
for (int i = 0; i < param->disc_res.num_prop; i++)
|
||||
{
|
||||
esp_bt_gap_dev_prop_t * prop = ¶m->disc_res.prop[i];
|
||||
if(prop->type != ESP_BT_GAP_DEV_PROP_EIR)
|
||||
{
|
||||
}
|
||||
if(prop->type == ESP_BT_GAP_DEV_PROP_BDNAME)
|
||||
{
|
||||
name = (uint8_t *) prop->val;
|
||||
name_len = strlen((const char *)name);
|
||||
}
|
||||
else if(prop->type == ESP_BT_GAP_DEV_PROP_RSSI)
|
||||
{
|
||||
rssi = *((int8_t *) prop->val);
|
||||
}
|
||||
else if(prop->type == ESP_BT_GAP_DEV_PROP_COD)
|
||||
{
|
||||
memcpy(&codv, prop->val, sizeof(uint32_t));
|
||||
}
|
||||
else if(prop->type == ESP_BT_GAP_DEV_PROP_EIR)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_CMPL_16BITS_UUID, &len);
|
||||
|
||||
if(data == nullptr)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_INCMPL_16BITS_UUID, &len);
|
||||
}
|
||||
|
||||
if(data && len == ESP_UUID_LEN_16)
|
||||
{
|
||||
uuid.len = ESP_UUID_LEN_16;
|
||||
uuid.uuid.uuid16 = data[0] + (data[1] << 8);
|
||||
continue;
|
||||
}
|
||||
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_CMPL_32BITS_UUID, &len);
|
||||
|
||||
if(data == nullptr)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_INCMPL_32BITS_UUID, &len);
|
||||
}
|
||||
|
||||
if(data && len == ESP_UUID_LEN_32)
|
||||
{
|
||||
uuid.len = len;
|
||||
memcpy(&uuid.uuid.uuid32, data, sizeof(uint32_t));
|
||||
continue;
|
||||
}
|
||||
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_CMPL_128BITS_UUID, &len);
|
||||
|
||||
if(data == nullptr)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_INCMPL_128BITS_UUID, &len);
|
||||
}
|
||||
|
||||
if(data && len == ESP_UUID_LEN_128)
|
||||
{
|
||||
uuid.len = len;
|
||||
memcpy(uuid.uuid.uuid128, (uint8_t *)data, len);
|
||||
continue;
|
||||
}
|
||||
|
||||
//try to find a name
|
||||
if (name == nullptr)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &len);
|
||||
|
||||
if (data == nullptr)
|
||||
{
|
||||
data = esp_bt_gap_resolve_eir_data((uint8_t *) prop->val, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &len);
|
||||
}
|
||||
|
||||
if (data && len)
|
||||
{
|
||||
name = data;
|
||||
name_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the found device is a peripheral or a second call on an existing device, add/update the device.
|
||||
if ((cod->major == ESP_BT_COD_MAJOR_DEV_PERIPHERAL) || (findValidScannedDevice(param->disc_res.bda, btCtrl.btScanList) != nullptr))
|
||||
{
|
||||
addBTScanDevice(param->disc_res.bda, cod, &uuid, name, name_len, rssi);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// BT GAP Event Handler.
|
||||
//
|
||||
void BT::processBTGapEvent(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
||||
{
|
||||
ESP_LOGI(TAG, "BT GAP DISC_STATE %s", (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) ? "START" : "STOP");
|
||||
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED)
|
||||
{
|
||||
// Release semaphore on which the initiator is waiting, this signals processing complete and results ready.
|
||||
xSemaphoreGive(pBTThis->btCtrl.bt_hidh_cb_semaphore);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_DISC_RES_EVT:
|
||||
{
|
||||
pBTThis->processBTDeviceScanResult(param);
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP KEY_NOTIF passkey:%d", param->key_notif.passkey);
|
||||
if(pBTThis->btCtrl.pairingHandler != nullptr) (*pBTThis->btCtrl.pairingHandler)(param->key_notif.passkey, 1);
|
||||
break;
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP MODE_CHG_EVT mode:%d", param->mode_chg.mode);
|
||||
break;
|
||||
case ESP_BT_GAP_AUTH_CMPL_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP MODE AUTH_CMPL:%s (%d)", param->auth_cmpl.device_name, param->auth_cmpl.stat);
|
||||
if(pBTThis->btCtrl.pairingHandler != nullptr) (*pBTThis->btCtrl.pairingHandler)((uint32_t)param->auth_cmpl.stat, 2);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "BT GAP EVENT %s", pBTThis->bt_gap_evt_str(event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Method to process a device data resulting from a BLE scan.
|
||||
//
|
||||
void BT::processBLEDeviceScanResult(esp_ble_gap_cb_param_t *param)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint16_t uuid = 0;
|
||||
uint16_t appearance = 0;
|
||||
char name[64] = "";
|
||||
uint8_t uuid_len = 0;
|
||||
uint8_t *uuid_d = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_16SRV_CMPL, &uuid_len);
|
||||
uint8_t appearance_len = 0;
|
||||
uint8_t *appearance_d = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_APPEARANCE, &appearance_len);
|
||||
uint8_t adv_name_len = 0;
|
||||
uint8_t *adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
|
||||
|
||||
if (uuid_d != nullptr && uuid_len)
|
||||
{
|
||||
uuid = uuid_d[0] + (uuid_d[1] << 8);
|
||||
}
|
||||
|
||||
if (appearance_d != nullptr && appearance_len)
|
||||
{
|
||||
appearance = appearance_d[0] + (appearance_d[1] << 8);
|
||||
}
|
||||
|
||||
if (adv_name == nullptr)
|
||||
{
|
||||
adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_SHORT, &adv_name_len);
|
||||
}
|
||||
|
||||
if (adv_name != nullptr && adv_name_len)
|
||||
{
|
||||
memcpy(name, adv_name, adv_name_len);
|
||||
name[adv_name_len] = 0;
|
||||
}
|
||||
|
||||
if (uuid == ESP_GATT_UUID_HID_SVC)
|
||||
{
|
||||
addBLEScanDevice(param->scan_rst.bda,
|
||||
param->scan_rst.ble_addr_type,
|
||||
appearance, adv_name, adv_name_len,
|
||||
param->scan_rst.rssi);
|
||||
}
|
||||
}
|
||||
|
||||
// BLE GAP Event Handler.
|
||||
//
|
||||
void BT::processBLEGapEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
// SCAN
|
||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE GAP EVENT SCAN_PARAM_SET_COMPLETE");
|
||||
|
||||
// Release semaphore, this releases the caller who initiated the scan as we are now complete.
|
||||
xSemaphoreGive(pBTThis->btCtrl.ble_hidh_cb_semaphore);
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_RESULT_EVT:
|
||||
{
|
||||
switch (param->scan_rst.search_evt)
|
||||
{
|
||||
case ESP_GAP_SEARCH_INQ_RES_EVT:
|
||||
{
|
||||
pBTThis->processBLEDeviceScanResult(param);
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_SEARCH_INQ_CMPL_EVT:
|
||||
ESP_LOGI(TAG, "BLE GAP EVENT SCAN DONE: %d", param->scan_rst.num_resps);
|
||||
|
||||
// Release semaphore, this releases the caller who initiated the scan as we are now complete.
|
||||
xSemaphoreGive(pBTThis->btCtrl.ble_hidh_cb_semaphore);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE GAP EVENT SCAN CANCELED");
|
||||
break;
|
||||
}
|
||||
|
||||
// ADVERTISEMENT
|
||||
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||
ESP_LOGI(TAG, "BLE GAP ADV_DATA_SET_COMPLETE");
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||
ESP_LOGI(TAG, "BLE GAP ADV_START_COMPLETE");
|
||||
break;
|
||||
|
||||
// AUTHENTICATION
|
||||
case ESP_GAP_BLE_AUTH_CMPL_EVT:
|
||||
if (!param->ble_security.auth_cmpl.success)
|
||||
{
|
||||
ESP_LOGE(TAG, "BLE GAP AUTH ERROR: 0x%x", param->ble_security.auth_cmpl.fail_reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE GAP AUTH SUCCESS");
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_KEY_EVT: //shows the ble key info share with peer device to the user.
|
||||
ESP_LOGI(TAG, "BLE GAP KEY type = %s", pBTThis->ble_key_type_str(param->ble_security.ble_key.key_type));
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: // ESP_IO_CAP_OUT
|
||||
// The app will receive this evt when the IO has Output capability and the peer device IO has Input capability.
|
||||
// Show the passkey number to the user to input it in the peer device.
|
||||
ESP_LOGI(TAG, "BLE GAP PASSKEY_NOTIF passkey:%d", param->ble_security.key_notif.passkey);
|
||||
if(pBTThis->btCtrl.pairingHandler != nullptr) (*pBTThis->btCtrl.pairingHandler)(param->ble_security.key_notif.passkey, 3);
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_NC_REQ_EVT: // ESP_IO_CAP_IO
|
||||
// The app will receive this event when the IO has DisplayYesNO capability and the peer device IO also has DisplayYesNo capability.
|
||||
// show the passkey number to the user to confirm it with the number displayed by peer device.
|
||||
ESP_LOGI(TAG, "BLE GAP NC_REQ passkey:%d", param->ble_security.key_notif.passkey);
|
||||
esp_ble_confirm_reply(param->ble_security.key_notif.bd_addr, true);
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_PASSKEY_REQ_EVT: // ESP_IO_CAP_IN
|
||||
// The app will receive this evt when the IO has Input capability and the peer device IO has Output capability.
|
||||
// See the passkey number on the peer device and send it back.
|
||||
ESP_LOGI(TAG, "BLE GAP PASSKEY_REQ");
|
||||
//esp_ble_passkey_reply(param->ble_security.ble_req.bd_addr, true, 1234);
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_SEC_REQ_EVT:
|
||||
ESP_LOGI(TAG, "BLE GAP SEC_REQ");
|
||||
// Send the positive(true) security response to the peer device to accept the security request.
|
||||
// If not accept the security request, should send the security response with negative(false) accept value.
|
||||
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
|
||||
ESP_LOGI(TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
|
||||
param->update_conn_params.status,
|
||||
param->update_conn_params.min_int,
|
||||
param->update_conn_params.max_int,
|
||||
param->update_conn_params.conn_int,
|
||||
param->update_conn_params.latency,
|
||||
param->update_conn_params.timeout);
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGI(TAG, "BLE GAP EVENT %s", pBTThis->ble_gap_evt_str(event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Method to scan for BT Classic devices.
|
||||
//
|
||||
esp_err_t BT::scanForBTDevices(uint32_t timeout)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
// Start BT GAP Discovery, wait for 'timeout' seconds for a valid result.
|
||||
if((result = esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, (int)(timeout / 1.28), 0)) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bt_gap_start_discovery failed: %d", result);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Method to scan for BLE Devices.
|
||||
//
|
||||
esp_err_t BT::scanForBLEDevices(uint32_t timeout)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t result = ESP_OK;
|
||||
// Setup BLE scan parameters structure, defined in ESP IDF documentation.
|
||||
static esp_ble_scan_params_t hid_scan_params = {
|
||||
.scan_type = BLE_SCAN_TYPE_ACTIVE,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_ENABLE,
|
||||
};
|
||||
|
||||
// Set scan parameters using populated structure.
|
||||
if((result = esp_ble_gap_set_scan_params(&hid_scan_params)) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ble_gap_set_scan_params failed: %d", result);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Wait for result, this is done by taking possession of a semaphore which is released in the callback when scan complete.
|
||||
xSemaphoreTake(btCtrl.ble_hidh_cb_semaphore, portMAX_DELAY);
|
||||
|
||||
if((result = esp_ble_gap_start_scanning(timeout)) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ble_gap_start_scanning failed: %d", result);
|
||||
return(result);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to scan for Bluetooth devices.
|
||||
//
|
||||
esp_err_t BT::scanForAllDevices(uint32_t timeout, size_t *noDevices, std::vector<t_scanListItem> &scanList)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
|
||||
// Clear previous lists.
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
btCtrl.btScanList.clear();
|
||||
#endif
|
||||
btCtrl.bleScanList.clear();
|
||||
|
||||
// Scan for BLE devices.
|
||||
if(scanForBLEDevices(timeout) == ESP_OK)
|
||||
{
|
||||
// Wait for result, this is done by taking possession of a semaphore which is released in the callback when scan complete.
|
||||
xSemaphoreTake(btCtrl.ble_hidh_cb_semaphore, portMAX_DELAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ESP_FAIL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Scan for BT devices
|
||||
if(scanForBTDevices(timeout) == ESP_OK)
|
||||
{
|
||||
// Wait for result, this is done by taking possession of a semaphore which is released in the callback when scan complete.
|
||||
xSemaphoreTake(btCtrl.bt_hidh_cb_semaphore, portMAX_DELAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ESP_FAIL);
|
||||
}
|
||||
#endif
|
||||
|
||||
//esp_bt_gap_cancel_discovery();
|
||||
//esp_ble_gap_stop_scanning();
|
||||
|
||||
// Process results into a merged list.
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
for(std::size_t idx = 0; idx < btCtrl.btScanList.size(); idx++)
|
||||
{
|
||||
scanList.push_back(btCtrl.btScanList[idx]);
|
||||
}
|
||||
#endif
|
||||
for(std::size_t idx = 0; idx < btCtrl.bleScanList.size(); idx++)
|
||||
{
|
||||
scanList.push_back(btCtrl.bleScanList[idx]);
|
||||
}
|
||||
|
||||
// Update the final list with display values.
|
||||
for(std::size_t idx = 0; idx < scanList.size(); idx++)
|
||||
{
|
||||
char buf[50];
|
||||
sprintf(buf, ESP_BD_ADDR_STR, ESP_BD_ADDR_HEX(scanList[idx].bda));
|
||||
scanList[idx].deviceAddr = buf;
|
||||
if(scanList[idx].transport == ESP_HID_TRANSPORT_BLE)
|
||||
{
|
||||
scanList[idx].deviceType = "BLE";
|
||||
}
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
if(scanList[idx].transport == ESP_HID_TRANSPORT_BT)
|
||||
{
|
||||
scanList[idx].deviceType = "BT";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Save number of entries.
|
||||
*noDevices = scanList.size();
|
||||
|
||||
// Clear BT/BLE lists as data no longer needed.
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
btCtrl.btScanList.clear();
|
||||
#endif
|
||||
btCtrl.bleScanList.clear();
|
||||
|
||||
return(ESP_OK);
|
||||
}
|
||||
|
||||
// Method to scan and build a list for all available devices.
|
||||
void BT::getDeviceList(std::vector<t_scanListItem> &scanList, int waitTime)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
size_t devicesFound = 0;
|
||||
|
||||
ESP_LOGD(TAG, "SCAN...");
|
||||
|
||||
// Clear previous entries.
|
||||
scanList.clear();
|
||||
|
||||
// Start scan for HID devices
|
||||
scanForAllDevices(waitTime, &devicesFound, scanList);
|
||||
|
||||
ESP_LOGD(TAG, "SCAN: %u results", devicesFound);
|
||||
}
|
||||
|
||||
// Method to configure Bluetooth and register required callbacks.
|
||||
bool BT::setup(t_pairingHandler *handler)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t result;
|
||||
const esp_bt_mode_t mode = HIDH_BTDM_MODE;
|
||||
uint8_t key_size = 16;
|
||||
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
|
||||
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
|
||||
uint32_t passkey = 123456;
|
||||
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE;
|
||||
uint8_t oob_support = ESP_BLE_OOB_DISABLE;
|
||||
|
||||
// Check for multiple instantiations, only one instance allowed.
|
||||
if(pBTThis != nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG, "Setup called more than once. Only one instance of BT is allowed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store current object and handlers.
|
||||
pBTThis = this;
|
||||
btCtrl.pairingHandler = handler;
|
||||
|
||||
// Bluetooth not enabled, exit.
|
||||
if(mode == HIDH_IDLE_MODE)
|
||||
{
|
||||
ESP_LOGE(TAG, "Please turn on BT HID host or BLE!");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Create BT Classic semaphore, used to halt caller whilst underlying receives and proceses data.
|
||||
btCtrl.bt_hidh_cb_semaphore = xSemaphoreCreateBinary();
|
||||
if (btCtrl.bt_hidh_cb_semaphore == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG, "xSemaphoreCreateMutex BT failed!");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create BLE semaphore, used to halt caller whilst underlying receives and proceses data.
|
||||
btCtrl.ble_hidh_cb_semaphore = xSemaphoreCreateBinary();
|
||||
if(btCtrl.ble_hidh_cb_semaphore == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG, "xSemaphoreCreateMutex BLE failed!");
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Delete BT semaphore as both BT and BLE need to be active, return fail to caller.
|
||||
vSemaphoreDelete(btCtrl.bt_hidh_cb_semaphore);
|
||||
btCtrl.bt_hidh_cb_semaphore = nullptr;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Setup default config for BT Classic.
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
bt_cfg.mode = mode;
|
||||
bt_cfg.bt_max_acl_conn = 3;
|
||||
bt_cfg.bt_max_sync_conn = 3;
|
||||
|
||||
// Configure Bluetooth controller for BT Classic operation.
|
||||
if((result = esp_bt_controller_init(&bt_cfg)))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bt_controller_init failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable Bluetooth Classic mode.
|
||||
if((result = esp_bt_controller_enable(mode)))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bt_controller_enable failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
esp_bredr_tx_power_set(ESP_PWR_LVL_P9, ESP_PWR_LVL_P9);
|
||||
#endif
|
||||
|
||||
// Setup and initialise Bluetooth BLE mode.
|
||||
if((result = esp_bluedroid_init()))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
if((result = esp_bluedroid_enable()))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
// Classic Bluetooth GAP
|
||||
esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
|
||||
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
|
||||
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
||||
|
||||
// Set default parameters for Legacy Pairing
|
||||
// Use fixed pin code
|
||||
//
|
||||
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED;
|
||||
esp_bt_pin_code_t pin_code;
|
||||
pin_code[0] = '1';
|
||||
pin_code[1] = '2';
|
||||
pin_code[2] = '3';
|
||||
pin_code[3] = '4';
|
||||
esp_bt_gap_set_pin(pin_type, 4, pin_code);
|
||||
|
||||
if((result = esp_bt_gap_register_callback(processBTGapEvent)))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bt_gap_register_callback failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow BT devices to connect back to us
|
||||
if((result = esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE)))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_bt_gap_set_scan_mode failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// BLE GAP
|
||||
if((result = esp_ble_gap_register_callback(processBLEGapEvent)))
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup security, no password.
|
||||
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND; // Bonding with peer device after authentication
|
||||
esp_ble_io_cap_t iocapble = ESP_IO_CAP_NONE; // Set the IO capability to No output No input
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocapble, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
|
||||
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
|
||||
|
||||
// Initialise parameters.
|
||||
btCtrl.batteryLevel = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Basic constructor, do nothing!
|
||||
BT::BT(void)
|
||||
{
|
||||
btCtrl.hidhDevHdl = NULL;
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
btCtrl.pairingHandler = nullptr;
|
||||
btCtrl.bt_hidh_cb_semaphore = nullptr;
|
||||
#endif
|
||||
btCtrl.ble_hidh_cb_semaphore = nullptr;
|
||||
pBTThis = NULL;
|
||||
//
|
||||
}
|
||||
|
||||
// Basic destructor, do nothing! Only ever called for instantiation of uninitialsed class to prove version data.Used for probing versions etc.
|
||||
BT::~BT(void)
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/BTHID.cpp
|
||||
1011
main/BTHID.cpp
Normal file
1011
main/BTHID.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/CMakeLists.txt
|
||||
4
main/CMakeLists.txt
Normal file
4
main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
set(COMPONENT_SRCS SharpKey.cpp NVS.cpp LED.cpp SWITCH.cpp KeyInterface.cpp MZ2528.cpp X1.cpp X68K.cpp Mouse.cpp MZ5665.cpp PC9801.cpp HID.cpp WiFi.cpp PS2KeyAdvanced.cpp PS2Mouse.cpp BT.cpp BTHID.cpp esp_efuse_custom_table.c)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "." "include")
|
||||
|
||||
register_component()
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/HID.cpp
|
||||
1018
main/HID.cpp
Normal file
1018
main/HID.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/Kconfig.projbuild
|
||||
309
main/Kconfig.projbuild
Normal file
309
main/Kconfig.projbuild
Normal file
@@ -0,0 +1,309 @@
|
||||
menu "SharpKey Configuration"
|
||||
|
||||
choice BUILD_TARGET
|
||||
prompt "Build target"
|
||||
default SHARPKEY
|
||||
help
|
||||
Choose the target of the next build, SHARPKEY for the multi-host SharpKey Interface, MZ25KEY_MZ2500 for the mz25key Interface which will be used
|
||||
with an MZ-2500 or MZ25KEY_MZ2800 for the mz25key Interface which will be used with an MZ-2800.
|
||||
|
||||
config SHARPKEY
|
||||
bool "SharpKey"
|
||||
help
|
||||
Target build for the SharpKey multi-host Interface.
|
||||
|
||||
config MZ25KEY_MZ2500
|
||||
bool "mz25key - MZ2500"
|
||||
help
|
||||
Target build for the mz25key Interface for use on an MZ-2500
|
||||
|
||||
config MZ25KEY_MZ2800
|
||||
bool "mz25key - MZ2800"
|
||||
help
|
||||
Target build for the mz25key Interface for use on an MZ-2800
|
||||
endchoice
|
||||
|
||||
choice FEATURE_SECURITY
|
||||
prompt "Runtime Feature Security"
|
||||
default DISABLE_FEATURE_SECURITY
|
||||
help
|
||||
Choose wether to enable features in the firmware based on fuse settings or to disable the feature.
|
||||
|
||||
config DISABLE_FEATURE_SECURITY
|
||||
bool "Disable feature security"
|
||||
help
|
||||
Disable the feature security, enabling all inbuilt modules of the SharpKey firmware.
|
||||
|
||||
config ENABLE_FEATURE_SECURITY
|
||||
bool "Enable feature security"
|
||||
help
|
||||
Enable feature security, modules will only be available if the corresponding eFuse is set.
|
||||
endchoice
|
||||
|
||||
menu "PS2 Keyboard"
|
||||
|
||||
config PS2_HW_DATAPIN
|
||||
int "GPIO pin number used for the PS/2 Keyboard DATA line"
|
||||
range 0 46
|
||||
default 14
|
||||
help
|
||||
GPIO number (IOxx) used to connect with the PS/2 Keyboard DATA line.
|
||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to I2C.
|
||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||
|
||||
config PS2_HW_CLKPIN
|
||||
int "GPIO pin number used for the PS/2 Keyboard CLK line"
|
||||
range 0 46
|
||||
default 13
|
||||
help
|
||||
GPIO number (IOxx) used to connect with the PS/2 Keyboard CLK line.
|
||||
This pin must be interrupt capable.
|
||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to I2C.
|
||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Host Interface"
|
||||
menu "4Bit Strobe Input"
|
||||
|
||||
config HOST_KDB0
|
||||
int "KDB0 GPIO pin number"
|
||||
range 0 46
|
||||
default 23
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 4bit bidirectional data bus Bit 0 with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDB1
|
||||
int "KDB1 GPIO pin number"
|
||||
range 0 46
|
||||
default 25
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 4bit bidirectional data bus Bit 1 with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDB2
|
||||
int "KDB2 GPIO pin number"
|
||||
range 0 46
|
||||
default 26
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 4bit bidirectional data bus Bit 2 with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDB3
|
||||
int "KDB3 GPIO pin number"
|
||||
range 0 46
|
||||
default 27
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 4bit bidirectional data bus Bit 3 with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
endmenu
|
||||
|
||||
menu "8Bit Scan Data Output"
|
||||
config HOST_KDO0
|
||||
int "KDO0 GPIO pin number"
|
||||
range 0 46
|
||||
default 14
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 0 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO1
|
||||
int "KDO1 GPIO pin number"
|
||||
range 0 46
|
||||
default 15
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 1 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO2
|
||||
int "KDO2 GPIO pin number"
|
||||
range 0 46
|
||||
default 16
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 2 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO3
|
||||
int "KDO3 GPIO pin number"
|
||||
range 0 46
|
||||
default 17
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 3 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO4
|
||||
int "KDO4 GPIO pin number"
|
||||
range 0 46
|
||||
default 18
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 4 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO5
|
||||
int "KDO5 GPIO pin number"
|
||||
range 0 46
|
||||
default 19
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 5 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO6
|
||||
int "KDO6 GPIO pin number"
|
||||
range 0 46
|
||||
default 21
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 6 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDO7
|
||||
int "KDO7 GPIO pin number"
|
||||
range 0 46
|
||||
default 21
|
||||
help
|
||||
GPIO number (IOxx) used to connect the 8bit scan data output Bit 7 to the 74HCT257 IC. See schematic for actual used value. May change with revisions.
|
||||
endmenu
|
||||
|
||||
choice MOUSE_UART_CHOICE
|
||||
prompt "Mouse host side UART"
|
||||
default HOST_BITBANG_UART
|
||||
help
|
||||
Select the hardware method of sending mouse data to the host. The two possible methods are bitbang (software UART) and UART Hardware.
|
||||
config HOST_BITBANG_UART
|
||||
bool "Bitbang UART"
|
||||
help
|
||||
Use the Bitbang UART (software).
|
||||
config HOST_HW_UART
|
||||
bool "Hardware UART"
|
||||
help
|
||||
Use one of the ESP32 Hardware UART's.
|
||||
endchoice
|
||||
|
||||
config HOST_RTSNI
|
||||
int "RTSNi GPIO pin number"
|
||||
range 0 46
|
||||
default 35
|
||||
help
|
||||
GPIO number (IOxx) used to connect the RTSN line with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_MPXI
|
||||
int "MPXi GPIO pin number"
|
||||
range 0 46
|
||||
default 12
|
||||
help
|
||||
GPIO number (IOxx) used to connect the MPX line with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
config HOST_KDI4
|
||||
int "KDI4 GPIO pin number"
|
||||
range 0 46
|
||||
default 13
|
||||
help
|
||||
GPIO number (IOxx) used to connect the KDI4 line with the ESP32. See schematic for actual used value. May change with revisions.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "WiFi"
|
||||
|
||||
config IF_WIFI_ENABLED
|
||||
bool "Enable WiFi connectivity"
|
||||
default false
|
||||
help
|
||||
Allow interface to act as an Access Point to allow external connectivity. Once connected the WiFi is intended to be used for making
|
||||
key mapping changes.
|
||||
This is an experimental feature and under development.
|
||||
|
||||
config IF_WIFI_EN_KEY
|
||||
int "WiFi Enable GPIO pin number"
|
||||
range 0 46
|
||||
default 34
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
GPIO number (IOxx) used by the WiFi En switch to enable wifi connectivity.
|
||||
|
||||
config IF_WIFI_SSID
|
||||
string "Default SSID in Access Point Mode"
|
||||
default "sharpkey"
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
The SSID broadcast whilst the sharpkey module advertises wireless connectivity.
|
||||
|
||||
config IF_WIFI_DEFAULT_SSID_PWD
|
||||
string "Default password for initial connection to Access Point Mode"
|
||||
default "sharpkey"
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
The initial password needed to connect and logon to access point.
|
||||
|
||||
config IF_WIFI_MAX_RETRIES
|
||||
int "Maximum number of connection retries."
|
||||
range 0 100
|
||||
default 10
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
Number of retries allowed for making a wireless connection with a client.
|
||||
|
||||
config IF_WIFI_AP_CHANNEL
|
||||
int "Channel of the Access Point."
|
||||
range 0 13
|
||||
default 7
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
Channel use by the Access Point, default is 7.
|
||||
|
||||
config IF_WIFI_SSID_HIDDEN
|
||||
int "Broadcast SSID?"
|
||||
range 0 1
|
||||
default 0
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
Broadcast the SSID (0) or hide it (1).
|
||||
|
||||
config IF_WIFI_MAX_CONNECTIONS
|
||||
int "Maximum simultaneous connections."
|
||||
range 0 20
|
||||
default 5
|
||||
depends on IF_WIFI_ENABLED
|
||||
help
|
||||
Maximum number of simultaneous open connections supported.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Debug Options"
|
||||
|
||||
config DEBUG_SERIAL
|
||||
bool "Serial debug output"
|
||||
default false
|
||||
help
|
||||
Enable debug output (non ESP logging) on the serial port.
|
||||
|
||||
config DEBUG_DISABLE_KDB
|
||||
bool "Disable input mode actuation of the KDB data bus"
|
||||
default false
|
||||
help
|
||||
Disable the Host KDB input configuration step, useful feature for debugging.
|
||||
|
||||
config DEBUG_DISABLE_KDO
|
||||
bool "Disable output mode actuation of the KDO strobe row"
|
||||
default false
|
||||
help
|
||||
Disable the Host KDO output configuration step, useful feature for debugging.
|
||||
|
||||
config DEBUG_DISABLE_RTSNI
|
||||
bool "Disable input mode actuation of the RTSNi signal"
|
||||
default false
|
||||
help
|
||||
Disable the Host RTSNi input configuration step, useful feature for debugging.
|
||||
|
||||
config DEBUG_DISABLE_MPXI
|
||||
bool "Disable input mode actuation of the MPXi signal"
|
||||
default false
|
||||
help
|
||||
Disable the Host MPXi input configuration step, useful feature for debugging.
|
||||
|
||||
config DEBUG_DISABLE_KDI
|
||||
bool "Disable input mode actuation of the KDI4 signal"
|
||||
default false
|
||||
help
|
||||
Disable the Host KDI input configuration step, useful feature for debugging.
|
||||
endmenu
|
||||
|
||||
config PWRLED
|
||||
int "GPIO pin number used for Power On and Status LED"
|
||||
range 0 46
|
||||
default 25
|
||||
help
|
||||
GPIO number (IOxx) used to control the Power On/Status LED.
|
||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to I2C.
|
||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/KeyInterface.cpp
|
||||
211
main/KeyInterface.cpp
Normal file
211
main/KeyInterface.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: KeyInterface.cpp
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Base class with virtual abstraction of key methods on which all host interfaces,
|
||||
// instantiated as a singleton, are based. This module comprises all common interface
|
||||
// code and the header contains the virtual abstraction methods overriden by the
|
||||
// sub-class which forms an actual interface.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "KeyInterface.h"
|
||||
|
||||
|
||||
// Method to reconfigure the GPIO on ADC2. This is necessary due to an ESP32 issue regarding WiFi Client mode and ADC2. If the
|
||||
// pins are input and wrong value the WiFi Client mode wont connect, if they are output it will connect!! A few issues with the
|
||||
// ESP32 you have to work around, next design, try use ADC2 as outputs only!
|
||||
void KeyInterface::reconfigADC2Ports(bool setAsOutput)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
gpio_config_t io_conf;
|
||||
|
||||
// Configure 4 inputs to be the Strobe Row Number which is used to index the virtual key matrix and the strobe data returned.
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_KDB)
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = (setAsOutput == true ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB0);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = (setAsOutput == true ? GPIO_PULLUP_DISABLE : GPIO_PULLUP_ENABLE);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB1);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB2);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB3);
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_KDI)
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = (setAsOutput == true ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDI4);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = (setAsOutput == true ? GPIO_PULLUP_DISABLE : GPIO_PULLUP_ENABLE);
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_MPXI)
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = (setAsOutput == true ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_HOST_MPXI);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = (setAsOutput == true ? GPIO_PULLUP_DISABLE : GPIO_PULLUP_ENABLE);
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
// In output mode set the drive capability to weak so as not to adversely affect the 74LS257.
|
||||
if(setAsOutput == true)
|
||||
{
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_KDB)
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_KDB0, GPIO_DRIVE_CAP_0);
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_KDB1, GPIO_DRIVE_CAP_0);
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_KDB2, GPIO_DRIVE_CAP_0);
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_KDB3, GPIO_DRIVE_CAP_0);
|
||||
#endif
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_KDI)
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_KDI4, GPIO_DRIVE_CAP_0);
|
||||
#endif
|
||||
#if !defined(CONFIG_DEBUG_DISABLE_MPXI)
|
||||
gpio_set_drive_capability((gpio_num_t)CONFIG_HOST_MPXI, GPIO_DRIVE_CAP_0);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to set the suspend flag. This is needed as some sub-class logic (ie. the MZ sub-class) locks and dedicates a core to meet
|
||||
// required timing. Unfortunately if using some Espressif/Arduino/FreeRTOS API modules (such as WiFi) and a core is held in a spinlock
|
||||
// it appears the API code has been written to use or attach to a fixed core thus the spinlock blocks its operation. Thus this method is provided
|
||||
// so that external logic such as WiFi can disable the interface during these situations.
|
||||
//
|
||||
void KeyInterface::suspendInterface(bool suspendIf)
|
||||
{
|
||||
this->suspend = suspendIf;
|
||||
}
|
||||
|
||||
// Method to test to see if the interface has been suspended.
|
||||
// Two modes, one just tests and returns the state, the second waits in a loop until the interface suspends.
|
||||
//
|
||||
bool KeyInterface::isSuspended(bool waitForSuspend)
|
||||
{
|
||||
// If flag set, loop waiting for the suspended flag to be set.
|
||||
while(waitForSuspend == true && this->suspended == false)
|
||||
{
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
||||
// Return the suspended status.
|
||||
return(this->suspended);
|
||||
}
|
||||
|
||||
// Method to test to see if the interface is running and not suspended.
|
||||
// Two modes, one just tests and returns the state, the second waits in a loop until the interface runs.
|
||||
bool KeyInterface::isRunning(bool waitForRelease)
|
||||
{
|
||||
// If flag set, loop waiting for the suspended flag to be set.
|
||||
while(waitForRelease == true && this->suspended == true)
|
||||
{
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
||||
// Return the suspended status.
|
||||
return(this->suspended);
|
||||
}
|
||||
|
||||
// Base initialisation for generic hardware used by all sub-classes. The sub-class invokes the init
|
||||
// method manually from within it's init method.
|
||||
void KeyInterface::init(const char *subClassName, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, uint32_t ifMode)
|
||||
{
|
||||
// Locals
|
||||
#define INITTAG "init"
|
||||
|
||||
// Store the NVS object.
|
||||
this->nvs = hdlNVS;
|
||||
|
||||
// Store the LED object.
|
||||
this->led = hdlLED;
|
||||
|
||||
// Store the HID object.
|
||||
this->hid = hdlHID;
|
||||
|
||||
// Store the sub-class name for later use, ie. NVS key access.
|
||||
this->subClassName = subClassName;
|
||||
|
||||
// Set LED to on.
|
||||
led->setLEDMode(LED::LED_MODE_ON, LED::LED_DUTY_CYCLE_OFF, 0, 0L, 0L);
|
||||
|
||||
// All done, no return code!
|
||||
return;
|
||||
}
|
||||
|
||||
// Base initialisation for generic hardware used by all sub-classes. The sub-class invokes the init
|
||||
// method manually from within it's init method.
|
||||
// This method doesnt initialise hardware, used for objects probing this object data.
|
||||
void KeyInterface::init(const char *subClassName, NVS *hdlNVS, HID *hdlHID)
|
||||
{
|
||||
// Locals
|
||||
#define INITTAG "init"
|
||||
|
||||
// Store the NVS object.
|
||||
this->nvs = hdlNVS;
|
||||
|
||||
// Store the HID object.
|
||||
this->hid = hdlHID;
|
||||
|
||||
// Store the sub-class name for later use, ie. NVS key access.
|
||||
this->subClassName = subClassName;
|
||||
|
||||
// All done, no return code!
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Constructor, basically initialise the Singleton interface and let the threads loose.
|
||||
//KeyInterface::KeyInterface(uint32_t ifMode)
|
||||
//{
|
||||
// // init(className(__PRETTY_FUNCTION__), ifMode);
|
||||
//}
|
||||
|
||||
// Basic constructor, do nothing!
|
||||
//KeyInterface::KeyInterface(void)
|
||||
//{
|
||||
// //
|
||||
//}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/LED.cpp
|
||||
341
main/LED.cpp
Normal file
341
main/LED.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: LED.cpp
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Base class for the encapsulation and control methods of an LED used primarily to
|
||||
// indicate to users the status of the application.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "LED.h"
|
||||
|
||||
// Method to set the LED mode, duty cycle and duty period. Once the current LED cycle has come to an end, the control
|
||||
// thread will replace the working configuration with the new configuration set here.
|
||||
//
|
||||
bool LED::setLEDMode(enum LED_MODE mode, enum LED_DUTY_CYCLE dutyCycle, uint32_t maxBlinks, uint64_t usDutyPeriod, uint64_t msInterPeriod)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
bool result = true;
|
||||
|
||||
// If a setup is already waiting to be processed, exit with fail. This could be stacked into a vector but not really beneficial.
|
||||
if(ledCtrl.newConfig.updated == false)
|
||||
{
|
||||
// Ensure we have exclusive access, the LED can be controlled by numerous threads, so ensure only one can access and setup at a time.
|
||||
if(xSemaphoreTake(ledCtrl.mutexInternal, (TickType_t)1000) == pdTRUE)
|
||||
{
|
||||
ledCtrl.newConfig.mode = mode;
|
||||
ledCtrl.newConfig.dutyCycle = dutyCycle;
|
||||
ledCtrl.newConfig.maxBlinks = maxBlinks;
|
||||
ledCtrl.newConfig.dutyPeriod = usDutyPeriod;
|
||||
ledCtrl.newConfig.interPeriod = msInterPeriod;
|
||||
ledCtrl.newConfig.updated = true;
|
||||
|
||||
// Release mutex so other threads can set the LED.
|
||||
xSemaphoreGive(ledCtrl.mutexInternal);
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Thread method to provide LED control.
|
||||
IRAM_ATTR void LED::ledInterface(void *pvParameters)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint32_t LED_MASK;
|
||||
uint64_t delayTimer = 0LL;
|
||||
uint64_t curTime = 0LL;
|
||||
enum LEDSTATE {
|
||||
LEDSTATE_IDLE = 0,
|
||||
LEDSTATE_BLINK_MARK = 1,
|
||||
LEDSTATE_BLINK_SPACE = 2,
|
||||
LEDSTATE_BLINK_INTER = 3,
|
||||
} fsmState = LEDSTATE_IDLE;
|
||||
#define LEDIFTAG "ledInterface"
|
||||
|
||||
// Map the instantiating object so we can access its methods and data.
|
||||
LED* pThis = (LED*)pvParameters;
|
||||
|
||||
// Set the LED GPIO mask according to the defined pin. This code needs updating if GPIO1 pins are used.
|
||||
LED_MASK = (1 << pThis->ledCtrl.ledPin);
|
||||
|
||||
// Sign on.
|
||||
ESP_LOGW("ledInterface", "Starting LED control thread.");
|
||||
|
||||
// Turn off LED.
|
||||
GPIO.out_w1tc = LED_MASK;
|
||||
|
||||
// Loops forever.
|
||||
for(;;)
|
||||
{
|
||||
// Check stack space, report if it is getting low.
|
||||
if(uxTaskGetStackHighWaterMark(NULL) < 1024)
|
||||
{
|
||||
ESP_LOGW(LEDIFTAG, "THREAD STACK SPACE(%d)\n",uxTaskGetStackHighWaterMark(NULL));
|
||||
}
|
||||
|
||||
// If a new configuration is set, then once the running FSM has returned to idle, update the configuration prior to the next FSM run.
|
||||
//
|
||||
if(pThis->ledCtrl.newConfig.updated)
|
||||
{
|
||||
// Take control of the Mutex so we are able to take on the data without a new setup clashing. If the Mutex is taken then continue on with the state machine logic till next loop.
|
||||
if(xSemaphoreTake(pThis->ledCtrl.mutexInternal, (TickType_t)1) == pdTRUE)
|
||||
{
|
||||
pThis->ledCtrl.currentConfig = pThis->ledCtrl.newConfig;
|
||||
pThis->ledCtrl.currentConfig.valid = true;
|
||||
pThis->ledCtrl.newConfig.updated = false;
|
||||
pThis->ledCtrl.blinkCnt = 0;
|
||||
|
||||
// Got new setup so release mutex.
|
||||
xSemaphoreGive(pThis->ledCtrl.mutexInternal);
|
||||
}
|
||||
}
|
||||
|
||||
// Only run if we have a valid configuration.
|
||||
if(pThis->ledCtrl.currentConfig.valid)
|
||||
{
|
||||
do {
|
||||
// Get the current timer value, only run the FSM when the timer is idle.
|
||||
timer_get_counter_value(TIMER_GROUP_0, TIMER_1, &curTime);
|
||||
if(curTime >= delayTimer)
|
||||
{
|
||||
// Ensure the timer is stopped.
|
||||
timer_pause(TIMER_GROUP_0, TIMER_1);
|
||||
delayTimer = 0LL;
|
||||
|
||||
// Mini finite state machine for LED control.
|
||||
switch(fsmState)
|
||||
{
|
||||
case LEDSTATE_IDLE:
|
||||
// For on/off, no need for the FSM, just apply setting to LED and loop.
|
||||
switch(pThis->ledCtrl.currentConfig.mode)
|
||||
{
|
||||
case LED_MODE_ON:
|
||||
// Turn on LED.
|
||||
GPIO.out_w1ts = LED_MASK;
|
||||
delayTimer = 1000UL;
|
||||
break;
|
||||
|
||||
case LED_MODE_BLINK_ONESHOT:
|
||||
// If the number of blinks is not 0 then on reaching the count, switch to LED off mode.
|
||||
if(pThis->ledCtrl.currentConfig.maxBlinks > 0 && pThis->ledCtrl.blinkCnt++ >= pThis->ledCtrl.currentConfig.maxBlinks)
|
||||
{
|
||||
pThis->ledCtrl.currentConfig.mode = LED_MODE_OFF;
|
||||
} else
|
||||
{
|
||||
fsmState = LEDSTATE_BLINK_MARK;
|
||||
}
|
||||
break;
|
||||
|
||||
case LED_MODE_BLINK:
|
||||
// Normal blink mode increments the count which is used for determining inter blink period.
|
||||
pThis->ledCtrl.blinkCnt++;
|
||||
fsmState = LEDSTATE_BLINK_MARK;
|
||||
break;
|
||||
|
||||
case LED_MODE_OFF:
|
||||
default:
|
||||
// Turn off LED.
|
||||
GPIO.out_w1tc = LED_MASK;
|
||||
delayTimer = 1000UL;
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case LEDSTATE_BLINK_MARK:
|
||||
// Turn on LED.
|
||||
GPIO.out_w1ts = LED_MASK;
|
||||
|
||||
// Next state, SPACE.
|
||||
fsmState = LEDSTATE_BLINK_SPACE;
|
||||
|
||||
// Calculate time to SPACE.
|
||||
switch(pThis->ledCtrl.currentConfig.dutyCycle)
|
||||
{
|
||||
case LED_DUTY_CYCLE_10:
|
||||
delayTimer = (pThis->ledCtrl.currentConfig.dutyPeriod / 10);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_20:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 2);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_30:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 3);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_40:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 4);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_50:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 5);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_60:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 6);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_70:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 7);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_80:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 8);
|
||||
break;
|
||||
case LED_DUTY_CYCLE_90:
|
||||
delayTimer = ((pThis->ledCtrl.currentConfig.dutyPeriod / 10) * 9);
|
||||
break;
|
||||
// We shouldnt be here if duty cycle is off, so back to idle.
|
||||
case LED_DUTY_CYCLE_OFF:
|
||||
default:
|
||||
GPIO.out_w1tc = LED_MASK;
|
||||
delayTimer = 0;
|
||||
fsmState = LEDSTATE_IDLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LEDSTATE_BLINK_SPACE:
|
||||
// Turn off LED.
|
||||
GPIO.out_w1tc = LED_MASK;
|
||||
|
||||
// Calculate time to next MARK.
|
||||
delayTimer = pThis->ledCtrl.currentConfig.dutyPeriod - delayTimer;
|
||||
|
||||
// Now add an interblink delay prior to next blink.
|
||||
fsmState = LEDSTATE_BLINK_INTER;
|
||||
break;
|
||||
|
||||
case LEDSTATE_BLINK_INTER:
|
||||
// If we are in normal mode with a blink limit set and limit reached or in limited mode, then add an interblink delay as configured.
|
||||
if((pThis->ledCtrl.currentConfig.mode == LED_MODE_BLINK && pThis->ledCtrl.currentConfig.maxBlinks > 0 && pThis->ledCtrl.blinkCnt >= pThis->ledCtrl.currentConfig.maxBlinks) ||
|
||||
(pThis->ledCtrl.currentConfig.mode == LED_MODE_BLINK_ONESHOT))
|
||||
{
|
||||
// Interblink delay is given in milli-seconds, so multiply up and set delay.
|
||||
delayTimer = pThis->ledCtrl.currentConfig.interPeriod * 1000;
|
||||
|
||||
// Reset blink counter to trigger next interperiod delay.
|
||||
if(pThis->ledCtrl.currentConfig.mode == LED_MODE_BLINK)
|
||||
pThis->ledCtrl.blinkCnt = 0;
|
||||
}
|
||||
|
||||
// We return to IDLE to allow time for reconfiguration if requested.
|
||||
fsmState = LEDSTATE_IDLE;
|
||||
break;
|
||||
|
||||
// Unknown or not programmed state, return to IDLE.
|
||||
default:
|
||||
fsmState = LEDSTATE_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If a new delay is requested, reset the value in the timer and start.
|
||||
if(delayTimer > 0LL)
|
||||
{
|
||||
timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0LL);
|
||||
timer_start(TIMER_GROUP_0, TIMER_1);
|
||||
}
|
||||
}
|
||||
|
||||
// Give the OS some time...
|
||||
taskYIELD();
|
||||
} while(fsmState != LEDSTATE_IDLE);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to set the GPIO pin to be used for LED output.
|
||||
void LED::ledInit(uint8_t ledPin)
|
||||
{
|
||||
// Initialise variables.
|
||||
this->ledCtrl.currentConfig.valid = false;
|
||||
this->ledCtrl.currentConfig.updated = false;
|
||||
this->ledCtrl.currentConfig.mode = LED_MODE_OFF;
|
||||
this->ledCtrl.currentConfig.dutyCycle = LED_DUTY_CYCLE_OFF;
|
||||
this->ledCtrl.currentConfig.dutyPeriod = 0LL;
|
||||
this->ledCtrl.currentConfig.interPeriod = 0LL;
|
||||
this->ledCtrl.newConfig = this->ledCtrl.currentConfig;
|
||||
|
||||
// Store GPIO pin to which LED is connected.
|
||||
this->ledCtrl.ledPin = ledPin;
|
||||
|
||||
// Configure a timer to be used for the LED blink rate.
|
||||
timer_config_t timerConfig = {
|
||||
.alarm_en = TIMER_ALARM_DIS, // No alarm, were not using interrupts as we are in a dedicated thread.
|
||||
.counter_en = TIMER_PAUSE, // Timer paused until required.
|
||||
.intr_type = TIMER_INTR_LEVEL, // No interrupts used.
|
||||
.counter_dir = TIMER_COUNT_UP, // Timing a fixed period.
|
||||
.auto_reload = TIMER_AUTORELOAD_DIS, // No need for auto reload, fixed time period.
|
||||
.divider = 80 // 1Mhz operation giving 1uS resolution.
|
||||
};
|
||||
ESP_ERROR_CHECK(timer_init(TIMER_GROUP_0, TIMER_1, &timerConfig));
|
||||
ESP_ERROR_CHECK(timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0));
|
||||
|
||||
// Setup mutex's.
|
||||
ledCtrl.mutexInternal = xSemaphoreCreateMutex();
|
||||
|
||||
// Core 0 - Application
|
||||
// LED control thread - dedicated thread to control the LED according to set mode.
|
||||
ESP_LOGW("ledInit", "Starting LEDif thread...");
|
||||
::xTaskCreatePinnedToCore(&this->ledInterface, "ledif", 4096, this, 0, &this->TaskLEDIF, 0);
|
||||
}
|
||||
|
||||
// Constructor, basically initialise the Singleton interface and let the control thread loose.
|
||||
LED::LED(uint32_t hwPin)
|
||||
{
|
||||
// Store the class name for later use, ie. NVS key access.
|
||||
this->className = getClassName(__PRETTY_FUNCTION__);
|
||||
|
||||
// Configure the Power LED used for activity and user interaction. Initial state is ON until a keyboard is detected when it turns off and only blinks on keyboard activity.
|
||||
ledInit(hwPin);
|
||||
|
||||
// Initial state, turn on LED to indicate LED control is working.
|
||||
setLEDMode(LED::LED_MODE_ON, LED::LED_DUTY_CYCLE_OFF, 0, 0L, 0L);
|
||||
}
|
||||
|
||||
// Basic constructor, do nothing!
|
||||
LED::LED(void)
|
||||
{
|
||||
// Store the class name for later use, ie. NVS key access.
|
||||
this->className = getClassName(__PRETTY_FUNCTION__);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/MZ2528.cpp
|
||||
1244
main/MZ2528.cpp
Normal file
1244
main/MZ2528.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/MZ5665.cpp
|
||||
1052
main/MZ5665.cpp
Normal file
1052
main/MZ5665.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/Mouse.cpp
|
||||
729
main/Mouse.cpp
Normal file
729
main/Mouse.cpp
Normal file
@@ -0,0 +1,729 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: Mouse.cpp
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: PS/2 Mouse to Sharp Host Interface logic.
|
||||
// This source file contains the singleton class containing logic to obtain
|
||||
// PS/2 mouse data (position, keys etc), map them into Sharp compatible codes and
|
||||
// transmit the data to the connected host.
|
||||
//
|
||||
// The whole application of which this class is a member, uses the Espressif Development
|
||||
// environment with Arduino components.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
// Updates to reflect moving functionality into the HID and to support
|
||||
// Bluetooth as a primary mouse or secondary mouse.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "Arduino.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "Mouse.h"
|
||||
|
||||
// Tag for ESP main application logging.
|
||||
#define MAINTAG "Mouse"
|
||||
|
||||
// Mouse Protocol
|
||||
// --------------
|
||||
//
|
||||
//
|
||||
// The Sharp (X68000/X1/MZ-2500/MZ-2800) mouse uses an asynchronous serial protocol over two wires (MSDATA/MSCTRL).
|
||||
// The MSCTRL signal is an enable signal, idle state = HIGH, it goes low prior to transmission of data by at least 1mS and goes high after
|
||||
// transmission of last bit by ~2.56mS.
|
||||
// The MSDATA signal is a standard asynchronous signal, idle = HIGH, 1 start bit, 8 data bits, 2 stop bits @ 4800baud.
|
||||
//
|
||||
// Protocol:
|
||||
// Idle State (MSDATA/MSCTRL) = High.
|
||||
// Transmission: MSCTRL -> LOW
|
||||
// 1ms delay
|
||||
// MSDATA -> low, first start bit.
|
||||
// 3 bytes transmitted in a <1xStart><8xdata><2xstop> format.
|
||||
// MSDATA -> high
|
||||
// 2.56ms delay.
|
||||
// MSCTRL -> HIGH
|
||||
// Data bytes: <CTRL><POS X><POS Y>
|
||||
// CTRL = [7] - Mouse rolling forward when high, backward when low.
|
||||
// [6]
|
||||
// [5] - Mouse rolling left, right when low.
|
||||
// [4]
|
||||
// [3]
|
||||
// [2]
|
||||
// [1] - Right button pressed = HIGH.
|
||||
// [0] - Left button pressed = HIGH.
|
||||
// POS X [7:0] - X Position data.
|
||||
// POS Y [7:0] - Y Position data.
|
||||
|
||||
|
||||
// Method to realise the Sharp host Mouse protocol.
|
||||
// This method uses Core 1 and it will hold it in a spinlock as necessary to ensure accurate timing.
|
||||
// Mouse data is passed into the method via a direct object, using the FreeRTOS Queue creates a time lag resulting in the mouse data being out of sync with hand movement.
|
||||
IRAM_ATTR void Mouse::hostInterface( void * pvParameters )
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
Mouse* pThis = (Mouse*)pvParameters; // Retrieve pointer to object in order to access data.
|
||||
bool msctrlEdge = false;
|
||||
uint8_t txBuf[4];
|
||||
uint32_t MSCTRL_MASK;
|
||||
uint32_t MSDATA_MASK;
|
||||
#ifdef CONFIG_HOST_BITBANG_UART
|
||||
int txPos;
|
||||
int txCnt;
|
||||
uint32_t shiftReg;
|
||||
uint64_t delayTimer = 0LL;
|
||||
uint64_t curTime = 0LL;
|
||||
uint32_t bitCount = 0;
|
||||
enum HOSTXMITSTATE {
|
||||
FSM_IDLE = 0,
|
||||
FSM_STARTXMIT = 1,
|
||||
FSM_STARTBIT = 2,
|
||||
FSM_DATA = 3,
|
||||
FSM_STOP = 4,
|
||||
FSM_ENDXMIT = 5
|
||||
} state = FSM_IDLE;
|
||||
#endif
|
||||
|
||||
// Initialise the MUTEX which prevents this core from being released to other tasks.
|
||||
pThis->x1Mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
if(pThis->hostControl.secondaryIf == false)
|
||||
{
|
||||
MSCTRL_MASK = (1 << CONFIG_HOST_KDB0);
|
||||
MSDATA_MASK = (1 << CONFIG_HOST_KDB1);
|
||||
} else
|
||||
{
|
||||
MSCTRL_MASK = (1 << CONFIG_HOST_KDB0);
|
||||
MSDATA_MASK = (1 << CONFIG_HOST_KDI4);
|
||||
}
|
||||
|
||||
gpio_config_t ioConf;
|
||||
ioConf.intr_type = GPIO_INTR_DISABLE;
|
||||
ioConf.mode = GPIO_MODE_INPUT;
|
||||
ioConf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
ioConf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
// Both Hardware UART and bitbang need MSCTRL setting as an input.
|
||||
if(pThis->hostControl.secondaryIf == false)
|
||||
{
|
||||
ioConf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB0);
|
||||
gpio_config(&ioConf);
|
||||
}
|
||||
// Bitbang mode also needs MSDATA setting as an output.
|
||||
#ifdef CONFIG_HOST_BITBANG_UART
|
||||
ioConf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
ioConf.mode = GPIO_MODE_OUTPUT;
|
||||
if(pThis->hostControl.secondaryIf == false)
|
||||
{
|
||||
ioConf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDB1);
|
||||
} else
|
||||
{
|
||||
ioConf.pin_bit_mask = (1ULL<<CONFIG_HOST_KDI4);
|
||||
}
|
||||
gpio_config(&ioConf);
|
||||
|
||||
// Set MSDATA to default state which is high.
|
||||
GPIO.out_w1ts = MSDATA_MASK;
|
||||
#endif
|
||||
|
||||
// Configure a timer to be used for the host mouse asynchronous protocol spacing with 1uS resolution. The default clock source is the APB running at 80MHz.
|
||||
timer_config_t timerConfig = {
|
||||
.alarm_en = TIMER_ALARM_DIS, // No alarm, were not using interrupts as we are in a dedicated thread.
|
||||
.counter_en = TIMER_PAUSE, // Timer paused until required.
|
||||
.intr_type = TIMER_INTR_LEVEL, // No interrupts used.
|
||||
.counter_dir = TIMER_COUNT_UP, // Timing a fixed period.
|
||||
.auto_reload = TIMER_AUTORELOAD_DIS, // No need for auto reload, fixed time period.
|
||||
.divider = 80 // 1Mhz operation giving 1uS resolution.
|
||||
};
|
||||
ESP_ERROR_CHECK(timer_init(TIMER_GROUP_0, TIMER_0, &timerConfig));
|
||||
ESP_ERROR_CHECK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0));
|
||||
|
||||
// Sign on.
|
||||
ESP_LOGW(MAINTAG, "Starting Host side Mouse thread.");
|
||||
|
||||
// Permanent loop, wait for an incoming message on the key to send queue, read it then transmit to the host, repeat!
|
||||
for(;;)
|
||||
{
|
||||
#ifdef CONFIG_HOST_BITBANG_UART
|
||||
// Get the current timer value, only run the FSM when the timer is idle.
|
||||
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &curTime);
|
||||
if((state == FSM_IDLE && pThis->hostControl.secondaryIf == false) || curTime >= delayTimer)
|
||||
{
|
||||
// Ensure the timer is stopped.
|
||||
timer_pause(TIMER_GROUP_0, TIMER_0);
|
||||
delayTimer = 0LL;
|
||||
|
||||
// Finite state machine to retrieve a key for transmission then serialise it according to the X1 protocol.
|
||||
switch(state)
|
||||
{
|
||||
case FSM_IDLE:
|
||||
// Yield if the suspend flag is set.
|
||||
pThis->yield(0);
|
||||
|
||||
// Check stack space, report if it is getting low.
|
||||
if(uxTaskGetStackHighWaterMark(NULL) < 1024)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "THREAD STACK SPACE(%d)\n",uxTaskGetStackHighWaterMark(NULL));
|
||||
}
|
||||
|
||||
if(pThis->hostControl.secondaryIf == false)
|
||||
{
|
||||
// Detect high to low edge. On mouse primary mode the MSCTRL signal forces the tempo. On mouse secondary mode (operating in tandem to keyboard),
|
||||
// the timer forces the tempo.
|
||||
//
|
||||
msctrlEdge = (REG_READ(GPIO_IN_REG) & MSCTRL_MASK) != 0 ? true : msctrlEdge;
|
||||
}
|
||||
|
||||
// Wait for a window when MSCTRL goes low.
|
||||
if(pThis->hostControl.secondaryIf == true || (msctrlEdge == true && (REG_READ(GPIO_IN_REG) & MSCTRL_MASK) == 0))
|
||||
{
|
||||
// Wait for incoming mouse movement message.
|
||||
if(pThis->xmitMsg.valid)
|
||||
{
|
||||
txBuf[0] = (uint8_t)pThis->xmitMsg.status;
|
||||
txBuf[1] = (uint8_t)pThis->xmitMsg.xPos;
|
||||
txBuf[2] = (uint8_t)pThis->xmitMsg.yPos;
|
||||
pThis->xmitMsg.valid = false; // Shouldnt be a race state here but consider a mutex if mouse gets out of sync.
|
||||
txBuf[3] = 0x00;
|
||||
txPos = 0;
|
||||
txCnt = 3;
|
||||
} else
|
||||
{
|
||||
// Sharp host protocol requires us to send zero change messages on a regular period regardless of new data.
|
||||
txBuf[0] = 0x00;
|
||||
txBuf[1] = 0x00;
|
||||
txBuf[2] = 0x00;
|
||||
txBuf[3] = 0x00;
|
||||
txPos = 0;
|
||||
txCnt = 3;
|
||||
}
|
||||
|
||||
// Advance to first start bit.
|
||||
state = FSM_STARTXMIT;
|
||||
|
||||
// Clear edge detect for next loop.
|
||||
msctrlEdge = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case FSM_STARTXMIT:
|
||||
// Ensure all variables and states correct before entering serialisation.
|
||||
GPIO.out_w1ts = MSDATA_MASK;
|
||||
state = FSM_STARTBIT;
|
||||
bitCount = 8;
|
||||
shiftReg = txBuf[txPos++];
|
||||
txCnt--;
|
||||
|
||||
// Create, initialise and hold a spinlock so the current core is bound to this one method.
|
||||
portENTER_CRITICAL(&pThis->x1Mutex);
|
||||
|
||||
break;
|
||||
|
||||
case FSM_STARTBIT:
|
||||
// Send out the start bit by bringing MSDATA low for 208us (4800 baud 1bit time period).
|
||||
GPIO.out_w1tc = MSDATA_MASK;
|
||||
delayTimer = BITBANG_UART_BIT_TIME;
|
||||
state = FSM_DATA;
|
||||
break;
|
||||
|
||||
case FSM_DATA:
|
||||
if(bitCount > 0)
|
||||
{
|
||||
// Setup the bit on MSDATA
|
||||
if(shiftReg & 0x00000001)
|
||||
{
|
||||
GPIO.out_w1ts = MSDATA_MASK;
|
||||
} else
|
||||
{
|
||||
GPIO.out_w1tc = MSDATA_MASK;
|
||||
}
|
||||
|
||||
// Shift the data to the next bit for transmission.
|
||||
shiftReg = shiftReg >> 1;
|
||||
|
||||
// 1 bit period.
|
||||
delayTimer = BITBANG_UART_BIT_TIME;
|
||||
|
||||
// 1 Less bit in frame.
|
||||
bitCount--;
|
||||
} else
|
||||
{
|
||||
state = FSM_STOP;
|
||||
}
|
||||
break;
|
||||
|
||||
case FSM_STOP:
|
||||
// Send out the stop bit, 2 are needed so just adjust the time delay.
|
||||
GPIO.out_w1ts = MSDATA_MASK;
|
||||
delayTimer = BITBANG_UART_BIT_TIME * 2;
|
||||
state = FSM_ENDXMIT;
|
||||
break;
|
||||
|
||||
case FSM_ENDXMIT:
|
||||
// End of critical timing loop, release the core so other tasks can run whilst we load up the next byte.
|
||||
portEXIT_CRITICAL(&pThis->x1Mutex);
|
||||
|
||||
// Any more bytes to transmit, loop and send if there are.
|
||||
if(txCnt > 0)
|
||||
{
|
||||
state = FSM_STARTXMIT;
|
||||
} else
|
||||
{
|
||||
// Reset timer for next loop.
|
||||
delayTimer = 20000UL;
|
||||
state = FSM_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// If a new delay is requested, set the value into the timer and start.
|
||||
if(delayTimer > 0LL)
|
||||
{
|
||||
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0LL);
|
||||
timer_start(TIMER_GROUP_0, TIMER_0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOST_HW_UART
|
||||
// Get the current timer value, we need to wait 20ms between transmissions.
|
||||
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &curTime);
|
||||
if(curTime >= delayTimer)
|
||||
{
|
||||
// Wait for a window when MSCTRL goes low.
|
||||
if(pThis->hostControl.secondaryIf == true || (REG_READ(GPIO_IN_REG) & MSCTRL_MASK) == 0)
|
||||
{
|
||||
// Ensure the timer is stopped, initialise to 0 and restart.
|
||||
timer_pause(TIMER_GROUP_0, TIMER_0);
|
||||
delayTimer = 20000LL;
|
||||
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0LL);
|
||||
timer_start(TIMER_GROUP_0, TIMER_0);
|
||||
|
||||
// Wait for incoming mouse movement message.
|
||||
if(pThis->xmitMsg.valid)
|
||||
{
|
||||
txBuf[0] = (uint8_t)pThis->xmitMsg.status;
|
||||
txBuf[1] = (uint8_t)pThis->xmitMsg.xPos;
|
||||
txBuf[2] = (uint8_t)pThis->xmitMsg.yPos;
|
||||
pThis->xmitMsg.valid = false; // Shouldnt be a race state here but consider a mutex if mouse gets out of sync.
|
||||
txBuf[3] = 0x00;
|
||||
txPos = 0;
|
||||
txCnt = 3;
|
||||
} else
|
||||
{
|
||||
// Sharp host protocol requires us to send zero change messages on a regular period regardless of new data.
|
||||
txBuf[0] = 0x00;
|
||||
txBuf[1] = 0x00;
|
||||
txBuf[2] = 0x00;
|
||||
txBuf[3] = 0x00;
|
||||
txPos = 0;
|
||||
txCnt = 3;
|
||||
}
|
||||
|
||||
// Send the bytes and wait.
|
||||
uart_write_bytes(pThis->hostControl.uartNum, (const char *)txBuf, 3);
|
||||
|
||||
// This method doesnt actually return after the last byte is transmitted, it returns well before, so we tack on a 10ms delay which is the width for 3 bytes at 4800 baud.
|
||||
uart_wait_tx_done(pThis->hostControl.uartNum, 25000);
|
||||
vTaskDelay(10);
|
||||
}
|
||||
|
||||
// Check stack space, report if it is getting low.
|
||||
if(uxTaskGetStackHighWaterMark(NULL) < 1024)
|
||||
{
|
||||
ESP_LOGW(MAPKEYTAG, "THREAD STACK SPACE(%d)\n",uxTaskGetStackHighWaterMark(NULL));
|
||||
}
|
||||
|
||||
// Yield if the suspend flag is set.
|
||||
pThis->yield(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Logic to feed the watchdog if needed. Watchdog disabled in menuconfig but if enabled this will need to be used.
|
||||
//TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; // write enable
|
||||
//TIMERG0.wdt_feed=1; // feed dog
|
||||
//TIMERG0.wdt_wprotect=0; // write protect
|
||||
//TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; // write enable
|
||||
//TIMERG1.wdt_feed=1; // feed dog
|
||||
//TIMERG1.wdt_wprotect=0; // write protect
|
||||
}
|
||||
}
|
||||
|
||||
// Primary HID routine.
|
||||
// This method is responsible for receiving HID (PS/2 or BT) mouse scan data and mapping it into Sharp compatible mouse data.
|
||||
// The HID mouse data once received is mapped and pushed onto a FIFO queue for transmission to the host.
|
||||
//
|
||||
void Mouse::mouseReceiveData(HID::t_mouseMessageElement mouseMessage)
|
||||
{
|
||||
// Locals.
|
||||
uint8_t status;
|
||||
|
||||
// Invert Y as the Sharp host is inverted compared to a PS/2 on the Y axis.
|
||||
mouseMessage.yPos = -mouseMessage.yPos;
|
||||
|
||||
// Initialise the status flag, on the Sharp host it is <Y Overflow><Y Underflow><X Overflow><X Underflow><1><0><Right Button><Left Button>
|
||||
status = (((mouseMessage.xPos >> 8) & 0x01) << 4) | (mouseMessage.status & 0x0F );
|
||||
|
||||
// Check bounds and set flags accordingly.
|
||||
if(mouseMessage.xPos > 127)
|
||||
{
|
||||
mouseMessage.xPos = 127; // Maximum resolution of Sharp host X movement.
|
||||
status |= (1UL << 4); // Set overflow bit.
|
||||
}
|
||||
if(mouseMessage.xPos < -128)
|
||||
{
|
||||
mouseMessage.xPos = -128; // Minimum resolution of Sharp host X movement.
|
||||
status |= (1UL << 5); // Set underflow bit.
|
||||
}
|
||||
if(mouseMessage.yPos > 127)
|
||||
{
|
||||
mouseMessage.yPos = 127; // Maximum resolution of Sharp host Y movement.
|
||||
status |= (1UL << 6); // Set overflow bit.
|
||||
}
|
||||
if(mouseMessage.yPos < -128)
|
||||
{
|
||||
mouseMessage.yPos = -128; // Minimum resolution of Sharp host Y movement.
|
||||
status |= (1UL << 7); // Set underflow bit.
|
||||
}
|
||||
|
||||
// Convert back to 8bit 2's compliment and store in the host message to the host thread.
|
||||
xmitMsg.xPos = (int8_t)mouseMessage.xPos;
|
||||
xmitMsg.yPos = (int8_t)mouseMessage.yPos;
|
||||
xmitMsg.status = status;
|
||||
xmitMsg.wheel = mouseMessage.wheel;
|
||||
xmitMsg.valid = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// A method to return the Type of data for a given column in the KeyMap table.
|
||||
//
|
||||
void Mouse::getMouseConfigTypes(std::vector<std::string>& typeList)
|
||||
{
|
||||
// Add the types.
|
||||
//
|
||||
typeList.push_back(HID_MOUSE_HOST_SCALING_TYPE);
|
||||
typeList.push_back(HID_MOUSE_SCALING_TYPE);
|
||||
typeList.push_back(HID_MOUSE_RESOLUTION_TYPE);
|
||||
typeList.push_back(HID_MOUSE_SAMPLING_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to return a list of key:value entries for a given config category. This represents the
|
||||
// feature which can be selected and the value it uses. Features can be combined by ORing the values
|
||||
// together.
|
||||
bool Mouse::getMouseSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
bool result = true;
|
||||
|
||||
// Build up a map, depending on the list required, of name to value. This list can then be used
|
||||
// by a user front end to select an option based on a name and return its value.
|
||||
if(option.compare(HID_MOUSE_HOST_SCALING_TYPE) == 0)
|
||||
{
|
||||
selectList.push_back(std::make_pair("ACTIVE", mouseConfig.host.scaling));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_HOST_SCALING_1_1_NAME, HID::HID_MOUSE_HOST_SCALING_1_1));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_HOST_SCALING_1_2_NAME, HID::HID_MOUSE_HOST_SCALING_1_2));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_HOST_SCALING_1_3_NAME, HID::HID_MOUSE_HOST_SCALING_1_3));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_HOST_SCALING_1_4_NAME, HID::HID_MOUSE_HOST_SCALING_1_4));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_HOST_SCALING_1_5_NAME, HID::HID_MOUSE_HOST_SCALING_1_5));
|
||||
}
|
||||
else if(option.compare(HID_MOUSE_SCALING_TYPE) == 0)
|
||||
{
|
||||
selectList.push_back(std::make_pair("ACTIVE", mouseConfig.mouse.scaling));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SCALING_1_1_NAME, HID::HID_MOUSE_SCALING_1_1));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SCALING_2_1_NAME, HID::HID_MOUSE_SCALING_2_1));
|
||||
}
|
||||
else if(option.compare(HID_MOUSE_RESOLUTION_TYPE) == 0)
|
||||
{
|
||||
selectList.push_back(std::make_pair("ACTIVE", mouseConfig.mouse.resolution));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_RESOLUTION_1_1_NAME, HID::HID_MOUSE_RESOLUTION_1_1));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_RESOLUTION_1_2_NAME, HID::HID_MOUSE_RESOLUTION_1_2));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_RESOLUTION_1_4_NAME, HID::HID_MOUSE_RESOLUTION_1_4));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_RESOLUTION_1_8_NAME, HID::HID_MOUSE_RESOLUTION_1_8));
|
||||
}
|
||||
else if(option.compare(HID_MOUSE_SAMPLING_TYPE) == 0)
|
||||
{
|
||||
selectList.push_back(std::make_pair("ACTIVE", mouseConfig.mouse.sampleRate));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_10_NAME, HID::HID_MOUSE_SAMPLE_RATE_10));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_20_NAME, HID::HID_MOUSE_SAMPLE_RATE_20));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_40_NAME, HID::HID_MOUSE_SAMPLE_RATE_40));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_60_NAME, HID::HID_MOUSE_SAMPLE_RATE_60));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_80_NAME, HID::HID_MOUSE_SAMPLE_RATE_80));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_100_NAME, HID::HID_MOUSE_SAMPLE_RATE_100));
|
||||
selectList.push_back(std::make_pair(HID_MOUSE_SAMPLE_RATE_200_NAME, HID::HID_MOUSE_SAMPLE_RATE_200));
|
||||
} else
|
||||
{
|
||||
// Not found!
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Return result, false if the option not found, true otherwise.
|
||||
//
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Public method to set the mouse configuration parameters.
|
||||
//
|
||||
bool Mouse::setMouseConfigValue(std::string paramName, std::string paramValue)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
bool dataError = false;
|
||||
int value(0);
|
||||
std::stringstream testVal(paramValue);
|
||||
|
||||
// Match the parameter name to a known mouse parameter, type and data check the parameter value and assign to the config accordingly.
|
||||
if(paramName.compare(HID_MOUSE_HOST_SCALING_TYPE) == 0)
|
||||
{
|
||||
// Exception handling is disabled, stringstream is used to catch bad input.
|
||||
dataError = (static_cast<bool>(testVal >> value) ? false : true);
|
||||
if(dataError == false)
|
||||
{
|
||||
if(value >= to_underlying(HID::HID_MOUSE_HOST_SCALING_1_1) && value <= to_underlying(HID::HID_MOUSE_HOST_SCALING_1_5))
|
||||
{
|
||||
mouseConfig.host.scaling = static_cast<HID::HID_MOUSE_HOST_SCALING>(value);
|
||||
hid->setMouseHostScaling(mouseConfig.host.scaling);
|
||||
} else
|
||||
{
|
||||
dataError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(paramName.compare(HID_MOUSE_SCALING_TYPE) == 0)
|
||||
{
|
||||
dataError = (static_cast<bool>(testVal >> value) ? false : true);
|
||||
if(dataError == false)
|
||||
{
|
||||
if(value >= to_underlying(HID::HID_MOUSE_SCALING_1_1) && value <= to_underlying(HID::HID_MOUSE_SCALING_2_1))
|
||||
{
|
||||
mouseConfig.mouse.scaling = static_cast<HID::HID_MOUSE_SCALING>(value);
|
||||
hid->setMouseScaling(mouseConfig.mouse.scaling);
|
||||
} else
|
||||
{
|
||||
dataError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(paramName.compare(HID_MOUSE_RESOLUTION_TYPE) == 0)
|
||||
{
|
||||
dataError = (static_cast<bool>(testVal >> value) ? false : true);
|
||||
if(dataError == false)
|
||||
{
|
||||
if(value >= to_underlying(HID::HID_MOUSE_RESOLUTION_1_1) && value <= to_underlying(HID::HID_MOUSE_RESOLUTION_1_8))
|
||||
{
|
||||
mouseConfig.mouse.resolution = static_cast<HID::HID_MOUSE_RESOLUTION>(value);
|
||||
hid->setMouseResolution(mouseConfig.mouse.resolution);
|
||||
} else
|
||||
{
|
||||
dataError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(paramName.compare(HID_MOUSE_SAMPLING_TYPE) == 0)
|
||||
{
|
||||
dataError = (static_cast<bool>(testVal >> value) ? false : true);
|
||||
if(dataError == false)
|
||||
{
|
||||
if(value >= to_underlying(HID::HID_MOUSE_SAMPLE_RATE_10) && value <= to_underlying(HID::HID_MOUSE_SAMPLE_RATE_200))
|
||||
{
|
||||
mouseConfig.mouse.sampleRate = static_cast<HID::HID_MOUSE_SAMPLING>(value);
|
||||
hid->setMouseSampleRate(mouseConfig.mouse.sampleRate);
|
||||
} else
|
||||
{
|
||||
dataError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error = true, success = false.
|
||||
return(dataError);
|
||||
}
|
||||
|
||||
// Method to save (persist) the configuration into NVS RAM.
|
||||
bool Mouse::persistConfig(void)
|
||||
{
|
||||
// Locals.
|
||||
bool result = true;
|
||||
|
||||
// Persist the data for next time.
|
||||
if(nvs->persistData(getClassName(__PRETTY_FUNCTION__), &this->mouseConfig, sizeof(t_mouseConfig)) == false)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "Persisting Mouse configuration data failed, check NVS setup.\n");
|
||||
result = false;
|
||||
}
|
||||
// Few other updates so make a commit here to ensure data is flushed and written.
|
||||
else if(nvs->commitData() == false)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "NVS Commit writes operation failed, some previous writes may not persist in future power cycles.");
|
||||
}
|
||||
|
||||
// Request persistence in the HID module.
|
||||
result |= hid->persistConfig();
|
||||
|
||||
// Error = false, success = true.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Initialisation routine. Start two threads, one to handle the incoming PS/2 mouse data and map it, the second to handle the host interface.
|
||||
void Mouse::init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID)
|
||||
{
|
||||
// Initialise control variables.
|
||||
#ifdef CONFIG_HOST_HW_UART
|
||||
hostControl.uartNum = UART_NUM_2;
|
||||
hostControl.uartBufferSize = 256;
|
||||
hostControl.uartQueueSize = 10;
|
||||
#endif
|
||||
|
||||
// Initialise the basic components.
|
||||
init(hdlNVS, hdlHID);
|
||||
|
||||
// Invoke the prototype init which initialises common variables and devices shared by all subclass.
|
||||
KeyInterface::init(getClassName(__PRETTY_FUNCTION__), hdlNVS, hdlLED, hdlHID, ifMode);
|
||||
|
||||
// There are two build possibilities, hardware UART and BITBANG. I initially coded using hardware but whilst trying to find a bug, wrote a bitbang
|
||||
// technique and both are fit for purpose, so enabling either yields the same result.
|
||||
#ifdef CONFIG_HOST_HW_UART
|
||||
// Prepare the UART to be used for communications with the Sharp host.
|
||||
// The Sharp host Mouse uses an Asynchronous protocol with 2 stop bits no parity 4800 baud.
|
||||
//
|
||||
uart_config_t uartConfig = {
|
||||
.baud_rate = 4800,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_2,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
|
||||
// Configure UART parameters and pin assignments, software flow control, not RTS/CTS.
|
||||
// The mouse only uses a Tx line, the MSCTRL line is used as a gate signal, so assign the Rx line to an unused pin.
|
||||
ESP_ERROR_CHECK(uart_param_config(hostControl.uartNum, &uartConfig));
|
||||
ESP_ERROR_CHECK(uart_set_pin(hostControl.uartNum, CONFIG_HOST_KDB1, CONFIG_HOST_KDB2, -1, -1));
|
||||
// Install UART driver. Use RX/TX buffers without event queue.
|
||||
ESP_ERROR_CHECK(uart_driver_install(hostControl.uartNum, hostControl.uartBufferSize, hostControl.uartBufferSize, 0, NULL, 0));
|
||||
#endif
|
||||
|
||||
// Register the streaming callback for the mouse, this will receive data, process it and send to the hostInterface for transmission to the host.
|
||||
hid->setDataCallback(&Mouse::mouseReceiveData, this);
|
||||
|
||||
// Create a task pinned to core 1 which will fulfill the Sharp Mouse host interface. This task has the highest priority
|
||||
// and it will also hold spinlock and manipulate the watchdog to ensure a scan cycle timing can be met. This means
|
||||
// all other tasks running on Core 1 will suspend as needed. The HID mouse controller will be serviced with core 0.
|
||||
//
|
||||
// Core 1 - Sharp Mouse Host Interface
|
||||
ESP_LOGW(MAINTAG, "Starting mouseIf thread...");
|
||||
::xTaskCreatePinnedToCore(&this->hostInterface, "mouseIf", 4096, this, 25, &this->TaskHostIF, 1);
|
||||
vTaskDelay(500);
|
||||
}
|
||||
|
||||
// Initialisation routine without hardware.
|
||||
void Mouse::init(NVS *hdlNVS, HID *hdlHID)
|
||||
{
|
||||
// Invoke the prototype init which initialises common variables and devices shared by all subclass.
|
||||
KeyInterface::init(getClassName(__PRETTY_FUNCTION__), hdlNVS, hdlHID);
|
||||
|
||||
// Retrieve configuration, if it doesnt exist, set defaults.
|
||||
//
|
||||
if(nvs->retrieveData(getClassName(__PRETTY_FUNCTION__), &this->mouseConfig, sizeof(t_mouseConfig)) == false)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "Mouse configuration set to default, no valid config in NVS found.");
|
||||
mouseConfig.mouse.resolution= HID::HID_MOUSE_RESOLUTION_1_8;
|
||||
mouseConfig.mouse.scaling = HID::HID_MOUSE_SCALING_1_1;
|
||||
mouseConfig.mouse.sampleRate= HID::HID_MOUSE_SAMPLE_RATE_60;
|
||||
mouseConfig.host.scaling = HID::HID_MOUSE_HOST_SCALING_1_2;
|
||||
|
||||
// Persist the data for next time.
|
||||
if(nvs->persistData(getClassName(__PRETTY_FUNCTION__), &this->mouseConfig, sizeof(t_mouseConfig)) == false)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "Persisting Default Mouse configuration data failed, check NVS setup.\n");
|
||||
}
|
||||
// Few other updates so make a commit here to ensure data is flushed and written.
|
||||
else if(nvs->commitData() == false)
|
||||
{
|
||||
ESP_LOGW(MAINTAG, "NVS Commit writes operation failed, some previous writes may not persist in future power cycles.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor, basically initialise the Singleton interface and let the threads loose.
|
||||
Mouse::Mouse(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID)
|
||||
{
|
||||
// Operating in uni-mode.
|
||||
hostControl.secondaryIf = false;
|
||||
|
||||
// Initialise the interface
|
||||
init(ifMode, hdlNVS, hdlLED, hdlHID);
|
||||
}
|
||||
|
||||
// Constructor, basic initialisation without hardware.
|
||||
Mouse::Mouse(NVS *hdlNVS, HID *hdlHID)
|
||||
{
|
||||
// Operating in uni-mode.
|
||||
hostControl.secondaryIf = false;
|
||||
|
||||
// Initialise the interface
|
||||
init(hdlNVS, hdlHID);
|
||||
}
|
||||
|
||||
// Constructor for use when mouse operates in tandem with a keyboard.
|
||||
Mouse::Mouse(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, bool secondaryIf)
|
||||
{
|
||||
// The interface can act in primary mode, ie. sole interface or secondary mode where it acts in tandem to a keyboard host. Slight processing differences occur
|
||||
// in secondary mode, for example, the pin used to output mouse data differs.
|
||||
hostControl.secondaryIf = secondaryIf;
|
||||
|
||||
// Initialise the interface
|
||||
init(ifMode, hdlNVS, hdlLED, hdlHID);
|
||||
}
|
||||
|
||||
// Constructor, used for version reporting so no hardware is initialised.
|
||||
Mouse::Mouse(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Destructor - only ever called when the class is used for version reporting.
|
||||
Mouse::~Mouse(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/NVS.cpp
|
||||
293
main/NVS.cpp
Normal file
293
main/NVS.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: NVS.cpp
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Base class for encapsulating the Espressif C API for the Non Volatile Storage.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "NVS.h"
|
||||
|
||||
// Method to externally take the NVS mutex for situations where another IDF module requires access to the NVS subsystem.
|
||||
//
|
||||
bool NVS::takeMutex(void)
|
||||
{
|
||||
// Locals.
|
||||
bool result = false;
|
||||
|
||||
// Ensure a handle has been opened to the NVS.
|
||||
if(nvsCtrl.nvsHandle != (nvs_handle_t)0)
|
||||
{
|
||||
// Request exclusive access.
|
||||
if(xSemaphoreTake(nvsCtrl.mutexInternal, (TickType_t)1000) == pdTRUE)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to release the NVS mutex previously taken.
|
||||
void NVS::giveMutex(void)
|
||||
{
|
||||
// Locals.
|
||||
|
||||
// Release mutex, external access now possible to the input devices.
|
||||
xSemaphoreGive(nvsCtrl.mutexInternal);
|
||||
}
|
||||
|
||||
// Method to persist data into the NVS RAM. This method takes a pointer to any memory object and writes it into the NVS using the handle opened at initialisation time.
|
||||
//
|
||||
bool NVS::persistData(const char *key, void *pData, uint32_t size)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t nvsStatus;
|
||||
bool result = true;
|
||||
#define NVSPERSISTTAG "persistData"
|
||||
|
||||
// Ensure a handle has been opened to the NVS.
|
||||
if(nvsCtrl.nvsHandle != (nvs_handle_t)0)
|
||||
{
|
||||
// Ensure we have exclusive access before accessing NVS.
|
||||
if(xSemaphoreTake(nvsCtrl.mutexInternal, (TickType_t)1000) == pdTRUE)
|
||||
{
|
||||
// Write a binary blob of data straight from memory pointed to by pData for readSize bytes into the NVS. This allows for individual variables or entire structures.
|
||||
nvsStatus = nvs_set_blob(this->nvsCtrl.nvsHandle, key, pData, size);
|
||||
if(nvsStatus != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(NVSPERSISTTAG, "Failed to persist NVS data, key:%s, size:%d, nvsStatus:%d", key, size, nvsStatus);
|
||||
result = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
// NB: Mutex only released in COMMIT.
|
||||
|
||||
// Return result code.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to retrieve persisted data from the NVS RAM. This method takes a pointer to a pre-allocated memoery block along with size and retrieves a data block from NVS upto size bytes.
|
||||
//
|
||||
bool NVS::retrieveData(const char *key, void *pData, uint32_t size)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t nvsStatus;
|
||||
size_t readSize = size;
|
||||
bool result = true;
|
||||
#define NVSRTRVTAG "retrieveData"
|
||||
|
||||
// Ensure a handle has been opened to the NVS.
|
||||
if(nvsCtrl.nvsHandle != (nvs_handle_t)0)
|
||||
{
|
||||
// Ensure we have exclusive access before accessing NVS.
|
||||
if(xSemaphoreTake(nvsCtrl.mutexInternal, (TickType_t)1000) == pdTRUE)
|
||||
{
|
||||
// Get a binary blob of data straight into the memory pointed to by pData for readSize. This allows for individual variables or entire structures.
|
||||
nvsStatus = nvs_get_blob(this->nvsCtrl.nvsHandle, key, pData, &readSize);
|
||||
if(nvsStatus != ESP_OK || readSize != size)
|
||||
{
|
||||
ESP_LOGW(NVSRTRVTAG, "Failed to retrieve NVS data, key:%s, size:%d, requested size:%d, nvsStatus:%d", key, readSize, size, nvsStatus);
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Release mutex, external access now possible to the input devices.
|
||||
xSemaphoreGive(nvsCtrl.mutexInternal);
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Return result code.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to ensure all data written to NVS is flushed and committed. This step is necessary as a write may be buffered and requires flushing to ensure persistence.
|
||||
//
|
||||
bool NVS::commitData(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
esp_err_t nvsStatus;
|
||||
bool result = true;
|
||||
#define NVSCOMMITTAG "commitData"
|
||||
|
||||
// Ensure a handle has been opened to the NVS.
|
||||
if(nvsCtrl.nvsHandle != (nvs_handle_t)0)
|
||||
{
|
||||
|
||||
// Check that the Mutex has been taken, if we grab it then it hasnt been taken in the persistData method, so exit as a call to persistData is mandatory.
|
||||
if(xSemaphoreTake(nvsCtrl.mutexInternal, (TickType_t)0) == pdTRUE)
|
||||
{
|
||||
xSemaphoreGive(nvsCtrl.mutexInternal);
|
||||
} else
|
||||
{
|
||||
// Request a commit transaction and return response accordingly.
|
||||
nvsStatus = nvs_commit(this->nvsCtrl.nvsHandle);
|
||||
if(nvsStatus != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(NVSCOMMITTAG, "Failed to commit pending NVS data.");
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Release mutex, external access now possible to the input devices.
|
||||
xSemaphoreGive(nvsCtrl.mutexInternal);
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Return result code.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Method to erase all the NVS and return to factory default state. The method closes any open handle,
|
||||
// de-initialises the NVS then performs a flash erase.
|
||||
//
|
||||
void NVS::eraseAll(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
#define NVSERATAG "eraseAll"
|
||||
|
||||
// Ensure we have exclusive access before accessing NVS.
|
||||
while(xSemaphoreTake(nvsCtrl.mutexInternal, (TickType_t)1000) != pdTRUE);
|
||||
|
||||
// Ensure a handle has been opened to the NVS.
|
||||
if(nvsCtrl.nvsHandle != (nvs_handle_t)0)
|
||||
{
|
||||
// Close open handle.
|
||||
nvs_close(nvsCtrl.nvsHandle);
|
||||
nvsCtrl.nvsHandle = NULL;
|
||||
}
|
||||
|
||||
// Stop the flash driver.
|
||||
nvs_flash_deinit();
|
||||
|
||||
ESP_LOGW(NVSERATAG, "Erasing flash, disable for production!\n");
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
|
||||
// Release mutex, external access now possible to the input devices.
|
||||
xSemaphoreGive(nvsCtrl.mutexInternal);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to initialise the NVS subsystem.
|
||||
void NVS::init(void)
|
||||
{
|
||||
// Locals.
|
||||
esp_err_t nvsStatus;
|
||||
#define NVSINITTAG "nvsInit"
|
||||
|
||||
// Initialise variables.
|
||||
nvsCtrl.nvsHandle = (nvs_handle_t)0;
|
||||
|
||||
//ESP_LOGW(NVSINITTAG, "Erasing flash, disable for production!\n");
|
||||
//ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
|
||||
// Initialize NVS
|
||||
ESP_LOGW(NVSINITTAG, "Initialising NVS.");
|
||||
nvsStatus = nvs_flash_init();
|
||||
if(nvsStatus == ESP_ERR_NVS_NO_FREE_PAGES || nvsStatus == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
// NVS partition was truncated and needs to be erased
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
|
||||
// Retry nvs_flash_init
|
||||
nvsStatus = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(nvsStatus);
|
||||
|
||||
// Setup mutex's.
|
||||
nvsCtrl.mutexInternal = xSemaphoreCreateMutex();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to open a namespace on the NVS given a key.
|
||||
//
|
||||
bool NVS::open(std::string keyName)
|
||||
{
|
||||
// Locals.
|
||||
bool result = true;
|
||||
#define NVSOPENTAG "nvsOpen"
|
||||
|
||||
// Only process if no handle has been opened. Currently only coded for one session at a time.
|
||||
if(nvsCtrl.nvsHandle == (nvs_handle_t)0)
|
||||
{
|
||||
// Store the key name under which all data is stored.
|
||||
this->nvsCtrl.nvsKeyName = keyName;
|
||||
|
||||
// Open handle to persistence using the base-class name as the key which represents the global namespace. Sub-classes and objects accessing the public methods will
|
||||
// use there own class name as a sub-key which represents the class namespace within NVS. Data is then stored within the class namespace using a key:value pair.
|
||||
esp_err_t nvsStatus = nvs_open(nvsCtrl.nvsKeyName.c_str(), NVS_READWRITE, &this->nvsCtrl.nvsHandle);
|
||||
if (nvsStatus != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(NVSOPENTAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(nvsStatus));
|
||||
result = false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Basic constructor, init variables!
|
||||
NVS::NVS(void)
|
||||
{
|
||||
// Store the class name for later use, ie. NVS key access.
|
||||
this->nvsCtrl.nvsClassName = getClassName(__PRETTY_FUNCTION__);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/PC9801.cpp
|
||||
1054
main/PC9801.cpp
Normal file
1054
main/PC9801.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/PS2KeyAdvanced.cpp
|
||||
1113
main/PS2KeyAdvanced.cpp
Normal file
1113
main/PS2KeyAdvanced.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/PS2Mouse.cpp
|
||||
682
main/PS2Mouse.cpp
Normal file
682
main/PS2Mouse.cpp
Normal file
@@ -0,0 +1,682 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: PS2Mouse.cpp
|
||||
// Created: Jan 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: PS/2 Mouse Class.
|
||||
// This source file contains the class to encapsulate a PS/2 mouse. Given two GPIO
|
||||
// pins, datapin and clkpin, it is able to communicate, configure and return mouse
|
||||
// data via a rich set of methods.
|
||||
//
|
||||
// This class borrows ideas from the interrupt concept of the PS2KeyAdvanced class
|
||||
// for communicating via the PS/2 protocol.
|
||||
// https://github.com/techpaul/PS2KeyAdvanced class from Paul Carpenter.
|
||||
//
|
||||
// The application uses the Espressif Development environment with Arduino components.
|
||||
// This is necessary as the class uses the Arduino methods for GPIO manipulation. I
|
||||
// was considering using pure Espressif IDF methods but considered the potential
|
||||
// of also using this class on an Arduino project.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PS2Mouse.h"
|
||||
|
||||
// Global handle to allow the static interrupt routine to access the instantiated object. This does limit this class to being Singleton
|
||||
// but it is unusual to have more than 1 PS/2 mouse on a project so less of a problem.
|
||||
PS2Mouse *pThis;
|
||||
|
||||
// Constructor. Simple assign the hardware data and clock pins to internal variables and setup
|
||||
// variables. Actual real initialisation is performed by a public method so re-initialisation can
|
||||
// be made if required.
|
||||
//
|
||||
PS2Mouse::PS2Mouse(int clockPin, int dataPin)
|
||||
{
|
||||
ps2Ctrl.clkPin = clockPin;
|
||||
ps2Ctrl.dataPin = dataPin;
|
||||
ps2Ctrl.supportsIntelliMouseExtensions = false;
|
||||
ps2Ctrl.mouseDataCallback = NULL;
|
||||
}
|
||||
|
||||
// Destructor - Detach interrupts and free resources.
|
||||
//
|
||||
PS2Mouse::~PS2Mouse()
|
||||
{
|
||||
// Disable interrupts.
|
||||
detachInterrupt( digitalPinToInterrupt( ps2Ctrl.clkPin ) );
|
||||
}
|
||||
|
||||
// The interrupt handler triggered on each falling edge of the clock pin.
|
||||
// Rx Mode: 11 bits - <start><8 data bits><ODD parity bit><stop bit>
|
||||
// Tx Mode: 11 bits - <start><8 data bits><ODD parity bit><stop bit>
|
||||
IRAM_ATTR void PS2Mouse::ps2interrupt( void )
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
static uint32_t timeLast = 0;
|
||||
uint32_t timeCurrent;
|
||||
uint8_t dataBit;
|
||||
|
||||
// Workaround for ESP32 SILICON error see extra/Porting.md
|
||||
#ifdef PS2_ONLY_CHANGE_IRQ
|
||||
if( digitalRead( ps2Ctrl.clkPin ) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
// TRANSMIT MODE.
|
||||
if( pThis->ps2Ctrl.mode & _TX_MODE )
|
||||
{
|
||||
// Received data not valid when transmitting.
|
||||
pThis->ps2Ctrl.rxPos = 0;
|
||||
|
||||
// Now point to next bit
|
||||
pThis->ps2Ctrl.bitCount++;
|
||||
|
||||
// BIT 1 - START BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 1)
|
||||
{
|
||||
#if defined( PS2_CLEAR_PENDING_IRQ )
|
||||
// Start bit due to Arduino bug
|
||||
digitalWrite(pThis->ps2Ctrl.dataPin, LOW);
|
||||
break;
|
||||
#endif
|
||||
} else
|
||||
// BIT 2->9 - DATA BIT MSB->LSB
|
||||
if(pThis->ps2Ctrl.bitCount >= 2 && pThis->ps2Ctrl.bitCount <= 9)
|
||||
{
|
||||
// Data bits
|
||||
dataBit = pThis->ps2Ctrl.shiftReg & 0x01; // get LSB
|
||||
digitalWrite(pThis->ps2Ctrl.dataPin, dataBit); // send start bit
|
||||
pThis->ps2Ctrl.parity += dataBit; // another one received ?
|
||||
pThis->ps2Ctrl.shiftReg >>= 1; // right _SHIFT one place for next bit
|
||||
} else
|
||||
// BIT 10 - PARITY BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 10)
|
||||
{
|
||||
// Parity - Send LSB if 1 = odd number of 1's so ps2Ctrl.parity should be 0
|
||||
digitalWrite( pThis->ps2Ctrl.dataPin, ( ~pThis->ps2Ctrl.parity & 1 ) );
|
||||
} else
|
||||
// BIT 11 - STOP BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 11)
|
||||
{
|
||||
// Stop bit write change to input pull up for high stop bit
|
||||
digitalWrite( pThis->ps2Ctrl.dataPin, HIGH );
|
||||
pinMode( pThis->ps2Ctrl.dataPin, INPUT );
|
||||
} else
|
||||
// BIT 12 - ACK BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 12)
|
||||
{
|
||||
// Acknowledge bit low we cannot do anything if high instead of low
|
||||
// clear modes to receive again
|
||||
pThis->ps2Ctrl.mode &= ~_TX_MODE;
|
||||
pThis->ps2Ctrl.bitCount = 0; // end of byte
|
||||
} else
|
||||
{
|
||||
// in case of weird error and end of byte reception re-sync
|
||||
pThis->ps2Ctrl.bitCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// RECEIVE MODE.
|
||||
else
|
||||
{
|
||||
// Read latest bit.
|
||||
dataBit = digitalRead( pThis->ps2Ctrl.dataPin );
|
||||
|
||||
// Get current time.
|
||||
timeCurrent = millis( );
|
||||
|
||||
// Reset the receive byte buffer pointer if the gap from the last received byte to the current time is greater than a packet interbyte delay.
|
||||
if(timeCurrent - timeLast > 100)
|
||||
{
|
||||
pThis->ps2Ctrl.rxPos = 0;
|
||||
}
|
||||
|
||||
// Catch glitches, any clock taking longer than 250ms is either a glitch, an error or start of a new packet.
|
||||
if( timeCurrent - timeLast > 250 )
|
||||
{
|
||||
pThis->ps2Ctrl.bitCount = 0;
|
||||
pThis->ps2Ctrl.shiftReg = 0;
|
||||
}
|
||||
|
||||
// Store current time for next loop to detect timing issues.
|
||||
timeLast = timeCurrent;
|
||||
|
||||
// Now point to next bit
|
||||
pThis->ps2Ctrl.bitCount++;
|
||||
|
||||
// BIT 1 - START BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 1)
|
||||
{
|
||||
// Start bit
|
||||
pThis->ps2Ctrl.parity = 0;
|
||||
pThis->ps2Ctrl.mode |= _PS2_BUSY; // set busy
|
||||
} else
|
||||
// BIT 2->9 - DATA BIT MSB->LSB
|
||||
if(pThis->ps2Ctrl.bitCount >= 2 && pThis->ps2Ctrl.bitCount <= 9)
|
||||
{
|
||||
// Data bits
|
||||
pThis->ps2Ctrl.parity += dataBit; // another one received ?
|
||||
pThis->ps2Ctrl.shiftReg >>= 1; // right _SHIFT one place for next bit
|
||||
pThis->ps2Ctrl.shiftReg |= ( dataBit ) ? 0x80 : 0; // or in MSbit
|
||||
} else
|
||||
// BIT 10 - PARITY BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 10)
|
||||
{
|
||||
// Parity check
|
||||
pThis->ps2Ctrl.parity &= 1; // Get LSB if 1 = odd number of 1's so ps2Ctrl.parity bit should be 0
|
||||
if( pThis->ps2Ctrl.parity == dataBit ) // Both same ps2Ctrl.parity error
|
||||
pThis->ps2Ctrl.parity = 0xFD; // To ensure at next bit count clear and discard
|
||||
} else
|
||||
// BIT 11 - STOP BIT
|
||||
if(pThis->ps2Ctrl.bitCount == 11)
|
||||
{
|
||||
// Streaming mode, assemble the data into the buffer.
|
||||
if(pThis->ps2Ctrl.streamingEnabled)
|
||||
{
|
||||
if(pThis->ps2Ctrl.rxPos == 0 && pThis->streaming.newData == true) pThis->streaming.overrun = true;
|
||||
if(pThis->ps2Ctrl.rxPos == 0) pThis->streaming.mouseData.status = pThis->ps2Ctrl.shiftReg;
|
||||
if(pThis->ps2Ctrl.rxPos == 1) pThis->streaming.mouseData.position.x = pThis->ps2Ctrl.shiftReg;
|
||||
if(pThis->ps2Ctrl.rxPos == 2) pThis->streaming.mouseData.position.y = pThis->ps2Ctrl.shiftReg;
|
||||
if(pThis->ps2Ctrl.rxPos == 3) pThis->streaming.mouseData.wheel = pThis->ps2Ctrl.shiftReg;
|
||||
if( (pThis->ps2Ctrl.supportsIntelliMouseExtensions == false && pThis->ps2Ctrl.rxPos == 2) || (pThis->ps2Ctrl.supportsIntelliMouseExtensions == true && pThis->ps2Ctrl.rxPos == 3))
|
||||
{
|
||||
pThis->streaming.newData = true;
|
||||
pThis->streaming.overrun = false;
|
||||
pThis->ps2Ctrl.rxPos = 0;
|
||||
} else
|
||||
{
|
||||
pThis->ps2Ctrl.rxPos++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// Save the received byte and parity, let consumer decide on it's validity.
|
||||
pThis->ps2Ctrl.rxBuf[pThis->ps2Ctrl.rxPos++] = (pThis->ps2Ctrl.parity << 8 | pThis->ps2Ctrl.shiftReg);
|
||||
}
|
||||
// Set mode and status for next receive byte
|
||||
pThis->ps2Ctrl.mode &= ~( _WAIT_RESPONSE );
|
||||
pThis->ps2Ctrl.mode &= ~_PS2_BUSY;
|
||||
pThis->ps2Ctrl.bitCount = 0; // end of byte
|
||||
} else
|
||||
{
|
||||
// in case of weird error and end of byte reception re-sync
|
||||
pThis->ps2Ctrl.bitCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to write a byte (control or parameter) to the Mouse. This method encapsulates the protocol necessary
|
||||
// to invoke Host -> PS/2 Mouse transmission and the interrupts, on falling clock edge, process the byte to send
|
||||
// and bitbang accordingly.
|
||||
//
|
||||
void PS2Mouse::writeByte(uint8_t command)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint32_t currentTime = millis();
|
||||
|
||||
// Test to see if a transmission is underway, block until the xmit buffer becomes available or timeout expires (no mouse).
|
||||
//
|
||||
while((ps2Ctrl.mode & _TX_MODE) && currentTime+100 > millis());
|
||||
|
||||
// If TX_MODE has been reset, interrupt processing has occurred so line up next byte,
|
||||
//
|
||||
if((ps2Ctrl.mode & _TX_MODE) == 0)
|
||||
{
|
||||
// Initialise the ps2 control variables.
|
||||
ps2Ctrl.shiftReg = command;
|
||||
ps2Ctrl.bitCount = 1;
|
||||
ps2Ctrl.parity = 0;
|
||||
ps2Ctrl.mode |= _TX_MODE + _PS2_BUSY;
|
||||
ps2Ctrl.rxPos = 0;
|
||||
|
||||
// Initialise the streaming buffer.
|
||||
streaming.mouseData.valid = false;
|
||||
streaming.mouseData.status = 0;
|
||||
streaming.mouseData.position.x = 0;
|
||||
streaming.mouseData.position.y = 0;
|
||||
streaming.mouseData.wheel = 0;
|
||||
streaming.newData = false;
|
||||
streaming.overrun = false;
|
||||
|
||||
// STOP the interrupt handler - Setting pin output low will cause interrupt before ready
|
||||
detachInterrupt( digitalPinToInterrupt( ps2Ctrl.clkPin ) );
|
||||
|
||||
// Set data and clock pins to output and high
|
||||
digitalWrite(ps2Ctrl.dataPin, HIGH);
|
||||
pinMode(ps2Ctrl.dataPin, OUTPUT);
|
||||
digitalWrite(ps2Ctrl.clkPin, HIGH);
|
||||
pinMode(ps2Ctrl.clkPin, OUTPUT);
|
||||
|
||||
// Essential for PS2 spec compliance
|
||||
delayMicroseconds(10);
|
||||
|
||||
// Set Clock LOW - trigger Host -> Mouse transmission. Mouse controls the clock but dragging clock low is used by the mouse to detect a host write and clock
|
||||
// data in accordingly.
|
||||
digitalWrite( ps2Ctrl.clkPin, LOW );
|
||||
|
||||
// Essential for PS2 spec compliance, set clock low for 60us
|
||||
delayMicroseconds(60);
|
||||
|
||||
// Set data low - Start bit
|
||||
digitalWrite( ps2Ctrl.dataPin, LOW );
|
||||
|
||||
// Set clock to input_pullup data stays output while writing to keyboard
|
||||
digitalWrite(ps2Ctrl.clkPin, HIGH);
|
||||
pinMode(ps2Ctrl.clkPin, INPUT);
|
||||
|
||||
// Restart interrupt handler
|
||||
attachInterrupt( digitalPinToInterrupt( ps2Ctrl.clkPin ), ps2interrupt, FALLING );
|
||||
}
|
||||
|
||||
// Everything is now processed in the interrupt handler.
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup and initialise the running object and Mouse hardware. This method must be called at startup and anytime a full reset is required.
|
||||
//
|
||||
void PS2Mouse::initialize()
|
||||
{
|
||||
// Setup variables.
|
||||
ps2Ctrl.mode = 0;
|
||||
ps2Ctrl.supportsIntelliMouseExtensions = false;
|
||||
ps2Ctrl.streamingEnabled = false;
|
||||
ps2Ctrl.bitCount = 0;
|
||||
ps2Ctrl.shiftReg = 0;
|
||||
ps2Ctrl.parity = 0;
|
||||
ps2Ctrl.rxPos = 0;
|
||||
// Clear the receive buffer.
|
||||
for(int idx=0; idx < 16; idx++) ps2Ctrl.rxBuf[idx] = 0x00;
|
||||
|
||||
// Set data and clock pins to input.
|
||||
digitalWrite(ps2Ctrl.dataPin, HIGH);
|
||||
pinMode(ps2Ctrl.dataPin, INPUT);
|
||||
digitalWrite(ps2Ctrl.clkPin, HIGH);
|
||||
pinMode(ps2Ctrl.clkPin, INPUT);
|
||||
|
||||
// Initialise the control structure.
|
||||
ps2Ctrl.bitCount = 0;
|
||||
ps2Ctrl.mode = 0;
|
||||
ps2Ctrl.rxPos = 0;
|
||||
|
||||
// As the interrupt handler is static it wont have reference to the instantiated object methods so we need to store the object in a pointer
|
||||
// which is then used by the interrupt handler.
|
||||
pThis = this;
|
||||
|
||||
// Attach the clock line to a falling low interrupt trigger and handler. The Mouse toggles the clock line for each bit to be sent/received
|
||||
// so we interrupt on each falling clock edge.
|
||||
attachInterrupt( digitalPinToInterrupt( ps2Ctrl.clkPin ), ps2interrupt, FALLING );
|
||||
|
||||
// Setup the mouse, make a reset, check and set Intellimouse extensions, set the resolution, scaling, sample rate to defaults and switch to remote (polled) mode.
|
||||
reset();
|
||||
checkIntelliMouseExtensions();
|
||||
setResolution(PS2_MOUSE_RESOLUTION_1_8);
|
||||
setScaling(PS2_MOUSE_SCALING_1_1);
|
||||
setSampleRate(PS2_MOUSE_SAMPLE_RATE_40);
|
||||
setRemoteMode();
|
||||
|
||||
// All done.
|
||||
return;
|
||||
}
|
||||
|
||||
// Public method to force a mouse reset. Used on startup and anytime the client believes the mouse has hungup.
|
||||
//
|
||||
bool PS2Mouse::reset(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
bool result = false;
|
||||
|
||||
// Send command to reset the mouse, if it returns an ACK then reset succeeded.
|
||||
//
|
||||
if(sendCmd(MOUSE_CMD_RESET, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Private method to check and see if the mouse suports Microsoft Intellimouse extensions. It sets an internal state flag accordingly.
|
||||
//
|
||||
bool PS2Mouse::checkIntelliMouseExtensions(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
char deviceId;
|
||||
|
||||
// IntelliMouse detection sequence, error checking isnt used.
|
||||
setSampleRate(PS2_MOUSE_SAMPLE_RATE_200);
|
||||
setSampleRate(PS2_MOUSE_SAMPLE_RATE_100);
|
||||
setSampleRate(PS2_MOUSE_SAMPLE_RATE_80);
|
||||
|
||||
// Get device Id and if the mouse supports Intellimouse extensions, it will reveal itself as an INTELLI_MOUSE.
|
||||
deviceId = getDeviceId();
|
||||
ps2Ctrl.supportsIntelliMouseExtensions = (deviceId == INTELLI_MOUSE);
|
||||
|
||||
// Return flag to indicate support (true) or no support (false).
|
||||
return(ps2Ctrl.supportsIntelliMouseExtensions);
|
||||
}
|
||||
|
||||
// Public method to set the automatic sample rate.
|
||||
//
|
||||
bool PS2Mouse::setSampleRate(enum PS2_SAMPLING rate)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
bool result = false;
|
||||
|
||||
// Sanity check.
|
||||
if(rate == PS2_MOUSE_SAMPLE_RATE_10 || rate == PS2_MOUSE_SAMPLE_RATE_20 || rate == PS2_MOUSE_SAMPLE_RATE_40 || rate == PS2_MOUSE_SAMPLE_RATE_60 || rate == PS2_MOUSE_SAMPLE_RATE_80 || rate == PS2_MOUSE_SAMPLE_RATE_100 || rate == PS2_MOUSE_SAMPLE_RATE_200)
|
||||
{
|
||||
// Send command to set the mouse resolution.
|
||||
//
|
||||
if(sendCmd(MOUSE_CMD_SET_SAMPLE_RATE, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
// Send the rate, if ACK is returned, then resolution set otherwise error.
|
||||
if(sendCmd((uint8_t)rate, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Public method to request the mouse Id which can be used to identify the mouse capabilities.
|
||||
//
|
||||
char PS2Mouse::getDeviceId(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
|
||||
// Send command to set the mouse scaling, either 2:1 or 1:1.
|
||||
//
|
||||
if(sendCmd(MOUSE_CMD_GET_DEVICE_ID, 1, respBuf, DEFAULT_MOUSE_TIMEOUT) == false)
|
||||
{
|
||||
respBuf[0] = 0xFF;
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(respBuf[0]);
|
||||
}
|
||||
|
||||
// Public method to set the mouse scaling, either Normal 1:1 (scaling = 0) or non-linear 2:1 (scaling = 1).
|
||||
//
|
||||
bool PS2Mouse::setScaling(enum PS2_SCALING scaling)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
bool result = false;
|
||||
|
||||
// Sanity check.
|
||||
if(scaling >= PS2_MOUSE_SCALING_1_1 && scaling < PS2_MOUSE_SCALING_2_1)
|
||||
{
|
||||
// Send command to set the mouse scaling, either 2:1 or 1:1.
|
||||
//
|
||||
if(sendCmd((uint8_t)scaling, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Public method to request the mouse enters remote mode.
|
||||
//
|
||||
bool PS2Mouse::setRemoteMode(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
|
||||
// Simply pass on the request to the mouse to enter remote mode.
|
||||
return(sendCmd(MOUSE_CMD_SET_REMOTE_MODE, 1, respBuf, DEFAULT_MOUSE_TIMEOUT));
|
||||
}
|
||||
|
||||
// Public method to request the mouse enters stream mode. This mode reports mouse movements as they change, albeit the streaming must also be enabled
|
||||
// once set to Stream Mode via the enableStreaming method.
|
||||
//
|
||||
bool PS2Mouse::setStreamMode(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
|
||||
// Simply pass on the request to the mouse to enter stream mode.
|
||||
return(sendCmd(MOUSE_CMD_SET_STREAM_MODE, 1, respBuf, DEFAULT_MOUSE_TIMEOUT));
|
||||
}
|
||||
|
||||
// Public methods to enable and disable streaming (constant rate packet transmission from mouse to host).
|
||||
// This module accepts the data and updates an in object set which the caller queries. No buffering takes place
|
||||
// so should the caller fail to read the data then the arrival of the next packet from the mouse will override
|
||||
// the in object values.
|
||||
//
|
||||
bool PS2Mouse::enableStreaming(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
|
||||
// Sanity check.
|
||||
if(ps2Ctrl.streamingEnabled == false)
|
||||
{
|
||||
if(sendCmd(MOUSE_CMD_ENABLE_STREAMING, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
// Initialise the streaming buffer.
|
||||
streaming.mouseData.valid = false;
|
||||
streaming.mouseData.status = 0;
|
||||
streaming.mouseData.position.x = 0;
|
||||
streaming.mouseData.position.y = 0;
|
||||
streaming.mouseData.wheel = 0;
|
||||
streaming.newData = false;
|
||||
streaming.overrun = false;
|
||||
ps2Ctrl.streamingEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the enabled flag to indicate success.
|
||||
return(ps2Ctrl.streamingEnabled);
|
||||
}
|
||||
bool PS2Mouse::disableStreaming(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
|
||||
// Sanity check.
|
||||
if(ps2Ctrl.streamingEnabled == true)
|
||||
{
|
||||
if(sendCmd(MOUSE_CMD_DISABLE_STREAMING, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
ps2Ctrl.streamingEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the enabled flag to indicate success.
|
||||
return(ps2Ctrl.streamingEnabled);
|
||||
}
|
||||
|
||||
// Public method to set the mouse resolution in pixels per millimeter, valid values are o..3.
|
||||
//
|
||||
bool PS2Mouse::setResolution(enum PS2_RESOLUTION resolution)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint8_t respBuf[5];
|
||||
bool result = false;
|
||||
|
||||
// Sanity check.
|
||||
if(resolution >= PS2_MOUSE_RESOLUTION_1_1 && resolution < PS2_MOUSE_RESOLUTION_1_8)
|
||||
{
|
||||
// Send command to set the mouse resolution.
|
||||
//
|
||||
if(sendCmd(MOUSE_CMD_SET_RESOLUTION, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
// Send the resolution, if ACK is returned, then resolution set otherwise error.
|
||||
if(sendCmd((uint8_t)resolution, 0, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Public method to get the current mouse status. The status code is 3 bytes wide and has the following format:
|
||||
//
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// Byte 1: 0 mode enable scaling 0 left btn middle right btn
|
||||
// Byte 2: resolution
|
||||
// Byte 3: sample rate
|
||||
//
|
||||
bool PS2Mouse::getStatus(uint8_t *respBuf)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
// Sanity check.
|
||||
if(respBuf != NULL)
|
||||
{
|
||||
// Send command to set the mouse resolution.
|
||||
//
|
||||
if(sendCmd(MOUSE_CMD_GET_STATUS, 3, respBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return result.
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Public method to obtain current mouse state data.
|
||||
//
|
||||
PS2Mouse::MouseData PS2Mouse::readData(void)
|
||||
{
|
||||
// Locals.
|
||||
MouseData data;
|
||||
uint8_t dataBuf[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
// If streaming mode enabled then set values according to data state. Data only valid if a new update has occurred since last call otherwise old data is returned and valid flag
|
||||
// is cleared.
|
||||
if(ps2Ctrl.streamingEnabled)
|
||||
{
|
||||
data.valid = streaming.newData;
|
||||
data.overrun = streaming.overrun;
|
||||
data.status = streaming.mouseData.status;
|
||||
data.position.x = streaming.mouseData.position.x;
|
||||
data.position.y = streaming.mouseData.position.y;
|
||||
data.wheel = ps2Ctrl.supportsIntelliMouseExtensions ? streaming.mouseData.wheel : 0;
|
||||
streaming.newData = false;
|
||||
streaming.overrun = false;
|
||||
|
||||
// If a data callback has been setup execute it otherwise data is read by caller.
|
||||
//
|
||||
if(ps2Ctrl.mouseDataCallback != NULL && data.valid)
|
||||
ps2Ctrl.mouseDataCallback(data);
|
||||
} else
|
||||
// Single on-request data set from mouse.
|
||||
{
|
||||
// Request data from mouse via issuing get single data packet command.
|
||||
if(requestData(ps2Ctrl.supportsIntelliMouseExtensions ? 3 : 3, dataBuf, DEFAULT_MOUSE_TIMEOUT))
|
||||
{
|
||||
data.valid = true;
|
||||
data.overrun = false;
|
||||
data.status = dataBuf[0];
|
||||
data.position.x = dataBuf[1];
|
||||
data.position.y = dataBuf[2];
|
||||
data.wheel = ps2Ctrl.supportsIntelliMouseExtensions ? dataBuf[3] : 0;
|
||||
} else
|
||||
{
|
||||
data.valid = false;
|
||||
data.overrun = false;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
// Method to request the latest mouse movement, wheel and key data. The method blocks until data is available or the timeout is reached. A timeout of 0
|
||||
// will only return when the data has been received.
|
||||
bool PS2Mouse::requestData(uint8_t expectedBytes, uint8_t *respBuf, uint32_t timeout)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
|
||||
// Simply pass on the request for the mouse to send data and await reply.
|
||||
return(sendCmd(MOUSE_CMD_REQUEST_DATA, expectedBytes, respBuf, timeout));
|
||||
}
|
||||
|
||||
// Method to send a command to the Mouse and await it's reply. If an ACK isnt returned then a resend request is made otherwise wait until all bytes
|
||||
// arrive or we timeout.
|
||||
//
|
||||
bool PS2Mouse::sendCmd(uint8_t cmd, uint8_t expectedBytes, uint8_t *respBuf, uint32_t timeout)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint32_t currentTime = millis();
|
||||
uint32_t endTime = millis() + timeout;
|
||||
uint8_t *pBuf = respBuf;
|
||||
bool result = false;
|
||||
|
||||
// Send command.
|
||||
writeByte(cmd);
|
||||
|
||||
// Wait for the expected number of bytes to arrive.
|
||||
while(((timeout == 0) || (currentTime < endTime)) && ps2Ctrl.rxPos <= expectedBytes)
|
||||
{
|
||||
// If an ACK isnt received, request a resend.
|
||||
if(ps2Ctrl.rxPos >= 1 && ps2Ctrl.rxBuf[0] != MOUSE_RESP_ACK) { writeByte(MOUSE_CMD_RESEND); }
|
||||
|
||||
// Get latest time.
|
||||
currentTime = millis();
|
||||
}
|
||||
|
||||
// Store the response in callers buffer.
|
||||
for(int idx=0; idx < expectedBytes; idx++)
|
||||
{
|
||||
(*pBuf) = ps2Ctrl.rxBuf[idx+1];
|
||||
pBuf++;
|
||||
}
|
||||
|
||||
// Set return code, true if a valid packet was received.
|
||||
if(((timeout == 0) || (currentTime < endTime)) && ps2Ctrl.rxPos >= expectedBytes && ps2Ctrl.rxBuf[0] == MOUSE_RESP_ACK) result = true;
|
||||
|
||||
// Debug print.
|
||||
//printf("%d:%d:%02x,%02x,%02x,%02x, %02x, %d, result=%d, %d, %d, %d\n", result, ps2Ctrl.rxPos, ps2Ctrl.rxBuf[0], ps2Ctrl.rxBuf[1], ps2Ctrl.rxBuf[2], ps2Ctrl.rxBuf[3],ps2Ctrl.rxBuf[4], ps2Ctrl.bitCount, result, timeout, currentTime, endTime);
|
||||
|
||||
// And complete with result!
|
||||
return(result);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/SWITCH.cpp
|
||||
216
main/SWITCH.cpp
Normal file
216
main/SWITCH.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: SWITCH.cpp
|
||||
// Created: May 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Base class for encapsulating the SharpKey WiFi/Config switch.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2022 - Initial write.
|
||||
// v1.00 Jun 2022 - Updates to add additional callbacks for RESET and CLEARNVS
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "SWITCH.h"
|
||||
|
||||
// Primary SWITCH thread, running on Core 0.
|
||||
// This thread is responsible for scanning the config/WiFi key on the SharpKey and generating callbacks according to state.
|
||||
//
|
||||
IRAM_ATTR void SWITCH::swInterface( void * pvParameters )
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
uint32_t keyDebCtr = 0;
|
||||
uint32_t WIFIEN_MASK = (1 << (CONFIG_IF_WIFI_EN_KEY - 32));
|
||||
uint32_t resetTimer = 0;
|
||||
#define WIFIIFTAG "swInterface"
|
||||
|
||||
// Map the instantiating object so we can access its methods and data.
|
||||
SWITCH* pThis = (SWITCH*)pvParameters;
|
||||
|
||||
// Loop indefinitely.
|
||||
while(true)
|
||||
{
|
||||
// Check the switch, has it gone to zero, ie. pressed?
|
||||
//
|
||||
if((REG_READ(GPIO_IN1_REG) & WIFIEN_MASK) == 0)
|
||||
{
|
||||
// First press detection turn LED off.
|
||||
if(keyDebCtr == 0)
|
||||
{
|
||||
pThis->led->setLEDMode(LED::LED_MODE_OFF, LED::LED_DUTY_CYCLE_OFF, 0, 0L, 0L);
|
||||
}
|
||||
// Entering WiFi enable mode, blink LED
|
||||
if(keyDebCtr == 10)
|
||||
{
|
||||
pThis->led->setLEDMode(LED::LED_MODE_BLINK, LED::LED_DUTY_CYCLE_50, 1, 50000L, 500L);
|
||||
}
|
||||
// Enter default AP mode.
|
||||
if(keyDebCtr == 50)
|
||||
{
|
||||
pThis->led->setLEDMode(LED::LED_MODE_BLINK, LED::LED_DUTY_CYCLE_30, 1, 25000L, 250L);
|
||||
}
|
||||
// Enter BT pairing mode.
|
||||
if(keyDebCtr == 100)
|
||||
{
|
||||
pThis->led->setLEDMode(LED::LED_MODE_BLINK, LED::LED_DUTY_CYCLE_10, 1, 10000L, 100L);
|
||||
}
|
||||
// Enter Clear NVS settings mode.
|
||||
if(keyDebCtr == 150)
|
||||
{
|
||||
pThis->led->setLEDMode(LED::LED_MODE_BLINK, LED::LED_DUTY_CYCLE_80, 5, 10000L, 1000L);
|
||||
}
|
||||
// Increment counter so we know how long it has been held.
|
||||
keyDebCtr++;
|
||||
} else
|
||||
if((REG_READ(GPIO_IN1_REG) & WIFIEN_MASK) != 0 && keyDebCtr > 1)
|
||||
{
|
||||
// On first 1/2 second press, if WiFi active, disable and reboot.
|
||||
if(keyDebCtr > 1 && keyDebCtr < 10)
|
||||
{
|
||||
// If a cancel callback has been setup, invoke it.
|
||||
//
|
||||
if(pThis->swCtrl.cancelEventCallback != NULL)
|
||||
pThis->swCtrl.cancelEventCallback();
|
||||
|
||||
// If the reset timer is running then a previous button press occurred. If it is less than 1 second then a RESET event
|
||||
// is required.
|
||||
if(resetTimer != 0 && (pThis->milliSeconds() - resetTimer) < 1000L)
|
||||
{
|
||||
// If a handler is installed call it. If the return value is true then a restart is possible. No handler then we just restart.
|
||||
if(pThis->swCtrl.resetEventCallback != NULL)
|
||||
{
|
||||
if(pThis->swCtrl.resetEventCallback())
|
||||
esp_restart();
|
||||
} else
|
||||
esp_restart();
|
||||
} else
|
||||
{
|
||||
resetTimer = pThis->milliSeconds();
|
||||
}
|
||||
}
|
||||
// If counter is in range 1 to 4 seconds then assume a WiFi on (so long as the client parameters have been configured).
|
||||
else if(keyDebCtr > 10 && keyDebCtr < 40)
|
||||
{
|
||||
// If a wifi enable callback has been setup, invoke it.
|
||||
//
|
||||
if(pThis->swCtrl.wifiEnEventCallback != NULL)
|
||||
pThis->swCtrl.wifiEnEventCallback();
|
||||
}
|
||||
// If the key is held for 5 or more seconds, then enter Wifi Config Default AP mode.
|
||||
else if(keyDebCtr > 50 && keyDebCtr < 100)
|
||||
{
|
||||
// If a wifi default enable callback has been setup, invoke it.
|
||||
//
|
||||
if(pThis->swCtrl.wifiDefEventCallback != NULL)
|
||||
pThis->swCtrl.wifiDefEventCallback();
|
||||
}
|
||||
// If the key is held for 10 seconds or more, invoke Bluetooth pairing mode.
|
||||
else if(keyDebCtr >= 100 && keyDebCtr < 150)
|
||||
{
|
||||
// If a bluetooth start pairing callback has been setup, invoke it.
|
||||
//
|
||||
if(pThis->swCtrl.btPairingEventCallback != NULL)
|
||||
pThis->swCtrl.btPairingEventCallback();
|
||||
}
|
||||
// If the key is held for 15 seconds or more, invoke the clear NVS settings (factory) mode.
|
||||
else if(keyDebCtr >= 150)
|
||||
{
|
||||
// If a clear NVS handler has been installed, call it.
|
||||
//
|
||||
if(pThis->swCtrl.clearNVSEventCallback != NULL)
|
||||
pThis->swCtrl.clearNVSEventCallback();
|
||||
}
|
||||
|
||||
// LED off, no longer needed.
|
||||
pThis->led->setLEDMode(LED::LED_MODE_OFF, LED::LED_DUTY_CYCLE_OFF, 0, 0L, 0L);
|
||||
|
||||
// Re-init switch variables for next activation.
|
||||
keyDebCtr = 0;
|
||||
}
|
||||
|
||||
// Reset the reset timer if not activated.
|
||||
if(resetTimer != 0 && (pThis->milliSeconds() - resetTimer) > 2000L) { resetTimer = 0; }
|
||||
|
||||
// Let other tasks run. NB. This value affects the debounce counter, update as necessary.
|
||||
vTaskDelay(100);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialisation routine. Setup variables and spawn a task to monitor the config switch.
|
||||
//
|
||||
void SWITCH::init(void)
|
||||
{
|
||||
// Initialise control variables.
|
||||
#define SWINITTAG "SWINIT"
|
||||
|
||||
// Core 0 - Application
|
||||
// SWITCH handler thread.
|
||||
ESP_LOGW(SWINITTAG, "Starting SWITCH thread...");
|
||||
::xTaskCreatePinnedToCore(&this->swInterface, "switch", 4096, this, 0, &this->swCtrl.TaskSWIF, 0);
|
||||
vTaskDelay(1500);
|
||||
}
|
||||
|
||||
// Basic constructor, init variables!
|
||||
SWITCH::SWITCH(LED *hdlLED)
|
||||
{
|
||||
swCtrl.cancelEventCallback = NULL;
|
||||
swCtrl.wifiEnEventCallback = NULL;
|
||||
swCtrl.wifiDefEventCallback = NULL;
|
||||
swCtrl.btPairingEventCallback = NULL;
|
||||
|
||||
// Store the class name for later use.
|
||||
this->swCtrl.swClassName = getClassName(__PRETTY_FUNCTION__);
|
||||
|
||||
// Save the LED object so it can be used to warn the user.
|
||||
this->led = hdlLED;
|
||||
|
||||
// Initialse the SWITCH object.
|
||||
init();
|
||||
}
|
||||
|
||||
// Basic consructor, do nothing!
|
||||
SWITCH::SWITCH(void)
|
||||
{
|
||||
// Store the class name for later use.
|
||||
this->swCtrl.swClassName = getClassName(__PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Basic destructor.
|
||||
SWITCH::~SWITCH(void)
|
||||
{
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/SharpKey.cpp
|
||||
1074
main/SharpKey.cpp
Normal file
1074
main/SharpKey.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/WiFi.cpp
|
||||
2872
main/WiFi.cpp
Normal file
2872
main/WiFi.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/X1.cpp
|
||||
1124
main/X1.cpp
Normal file
1124
main/X1.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/X68K.cpp
|
||||
1067
main/X68K.cpp
Normal file
1067
main/X68K.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../sharpkey/main/component.mk
|
||||
8
main/component.mk
Normal file
8
main/component.mk
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Main component makefile.
|
||||
#
|
||||
# This Makefile can be left empty. By default, it will take the sources in the
|
||||
# src/ directory, compile them and link them into lib(subdirectory_name).a
|
||||
# in the build directory. This behaviour is entirely configurable,
|
||||
# please read the ESP-IDF documents if you need to do this.
|
||||
#
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/BT.h
|
||||
222
main/include/BT.h
Normal file
222
main/include/BT.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: BT.h
|
||||
// Created: Jan 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header file for the Bluetooth Class.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BT_H_
|
||||
#define BT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_hidh.h"
|
||||
#include "esp_hid_common.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
|
||||
// Bluetooth interface class. Provides Mouse and Keyboard functionality via the Bluetooth wireless interface.
|
||||
class BT {
|
||||
#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(*a))
|
||||
|
||||
public:
|
||||
typedef void t_pairingHandler(uint32_t code, uint8_t trigger);
|
||||
|
||||
// Structure to contain details of a single device forming a scanned device list.
|
||||
//
|
||||
typedef struct {
|
||||
esp_bd_addr_t bda;
|
||||
std::string name;
|
||||
int8_t rssi;
|
||||
esp_hid_usage_t usage;
|
||||
esp_hid_transport_t transport; //BT, BLE or USB
|
||||
|
||||
union {
|
||||
struct {
|
||||
esp_bt_cod_t cod;
|
||||
esp_bt_uuid_t uuid;
|
||||
} bt;
|
||||
struct {
|
||||
esp_ble_addr_type_t addr_type;
|
||||
uint16_t appearance;
|
||||
} ble;
|
||||
};
|
||||
|
||||
// Display format values.
|
||||
std::string deviceAddr; // MAC address of the Bluetooth device.
|
||||
std::string deviceType; // BT, BLE or USB
|
||||
} t_scanListItem;
|
||||
|
||||
|
||||
// Prototypes.
|
||||
BT(void);
|
||||
virtual ~BT(void);
|
||||
void getDeviceList(std::vector<t_scanListItem> &scanList, int waitTime);
|
||||
bool setup(t_pairingHandler *handler = nullptr);
|
||||
|
||||
inline uint8_t getBatteryLevel() { return btCtrl.batteryLevel; }
|
||||
inline void setBatteryLevel(uint8_t level) { btCtrl.batteryLevel = level; }
|
||||
|
||||
private:
|
||||
static constexpr char const *TAG = "BT";
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
const char *gap_bt_prop_type_names[5] = { "", "BDNAME", "COD", "RSSI", "EIR" };
|
||||
const char *bt_gap_evt_names[10] = { "DISC_RES", "DISC_STATE_CHANGED", "RMT_SRVCS", "RMT_SRVC_REC", "AUTH_CMPL", "PIN_REQ", "CFM_REQ", "KEY_NOTIF", "KEY_REQ", "READ_RSSI_DELTA" };
|
||||
#endif
|
||||
const char *ble_gap_evt_names[28] = { "ADV_DATA_SET_COMPLETE", "SCAN_RSP_DATA_SET_COMPLETE", "SCAN_PARAM_SET_COMPLETE", "SCAN_RESULT", "ADV_DATA_RAW_SET_COMPLETE",
|
||||
"SCAN_RSP_DATA_RAW_SET_COMPLETE", "ADV_START_COMPLETE", "SCAN_START_COMPLETE", "AUTH_CMPL", "KEY",
|
||||
"SEC_REQ", "PASSKEY_NOTIF", "PASSKEY_REQ", "OOB_REQ", "LOCAL_IR",
|
||||
"LOCAL_ER", "NC_REQ", "ADV_STOP_COMPLETE", "SCAN_STOP_COMPLETE", "SET_STATIC_RAND_ADDR",
|
||||
"UPDATE_CONN_PARAMS", "SET_PKT_LENGTH_COMPLETE", "SET_LOCAL_PRIVACY_COMPLETE", "REMOVE_BOND_DEV_COMPLETE", "CLEAR_BOND_DEV_COMPLETE",
|
||||
"GET_BOND_DEV_COMPLETE", "READ_RSSI_COMPLETE", "UPDATE_WHITELIST_COMPLETE" };
|
||||
const char *ble_addr_type_names[4] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" };
|
||||
|
||||
// Define possible HIDH host modes.
|
||||
static const esp_bt_mode_t HIDH_IDLE_MODE = (esp_bt_mode_t) 0x00;
|
||||
static const esp_bt_mode_t HIDH_BLE_MODE = (esp_bt_mode_t) 0x01;
|
||||
static const esp_bt_mode_t HIDH_BT_MODE = (esp_bt_mode_t) 0x02;
|
||||
static const esp_bt_mode_t HIDH_BTDM_MODE = (esp_bt_mode_t) 0x03;
|
||||
|
||||
// Structure to maintain control variables.
|
||||
typedef struct {
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
std::vector<t_scanListItem> btScanList;
|
||||
#endif
|
||||
std::vector<t_scanListItem> bleScanList;
|
||||
|
||||
t_pairingHandler *pairingHandler;
|
||||
esp_hidh_dev_t *hidhDevHdl;
|
||||
|
||||
int8_t batteryLevel;
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
xSemaphoreHandle bt_hidh_cb_semaphore;
|
||||
#endif
|
||||
xSemaphoreHandle ble_hidh_cb_semaphore;
|
||||
|
||||
BT *pThis;
|
||||
} t_btCtrl;
|
||||
|
||||
// All control variables are stored in a struct for ease of reference.
|
||||
t_btCtrl btCtrl;
|
||||
|
||||
|
||||
// Prototypes.
|
||||
static void processBTGapEvent(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t * param);
|
||||
static void processBLEGapEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
|
||||
t_scanListItem* findValidScannedDevice(esp_bd_addr_t bda, std::vector<t_scanListItem> &scanList);
|
||||
void processBLEDeviceScanResult(esp_ble_gap_cb_param_t * scan_rst);
|
||||
void addBLEScanDevice(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type, uint16_t appearance, uint8_t *name, uint8_t name_len, int rssi);
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
void processBTDeviceScanResult(esp_bt_gap_cb_param_t * param);
|
||||
void addBTScanDevice(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid_t *uuid, uint8_t *name, uint8_t name_len, int rssi);
|
||||
#endif
|
||||
esp_err_t scanForBLEDevices(uint32_t timeout);
|
||||
esp_err_t scanForBTDevices(uint32_t timeout);
|
||||
esp_err_t scanForAllDevices(uint32_t timeout, size_t *noDevices, std::vector<t_scanListItem> &scanList);
|
||||
void printUUID(esp_bt_uuid_t * uuid);
|
||||
|
||||
const char *ble_addr_type_str(esp_ble_addr_type_t ble_addr_type)
|
||||
{
|
||||
if (ble_addr_type > BLE_ADDR_TYPE_RPA_RANDOM)
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return ble_addr_type_names[ble_addr_type];
|
||||
}
|
||||
|
||||
const char *ble_gap_evt_str(uint8_t event)
|
||||
{
|
||||
if (event >= SIZEOF_ARRAY(ble_gap_evt_names))
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return ble_gap_evt_names[event];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLASSIC_BT_ENABLED
|
||||
const char *bt_gap_evt_str(uint8_t event)
|
||||
{
|
||||
if (event >= SIZEOF_ARRAY(bt_gap_evt_names))
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return bt_gap_evt_names[event];
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *ble_key_type_str(esp_ble_key_type_t key_type)
|
||||
{
|
||||
const char *key_str = nullptr;
|
||||
switch (key_type)
|
||||
{
|
||||
case ESP_LE_KEY_NONE:
|
||||
key_str = "ESP_LE_KEY_NONE";
|
||||
break;
|
||||
case ESP_LE_KEY_PENC:
|
||||
key_str = "ESP_LE_KEY_PENC";
|
||||
break;
|
||||
case ESP_LE_KEY_PID:
|
||||
key_str = "ESP_LE_KEY_PID";
|
||||
break;
|
||||
case ESP_LE_KEY_PCSRK:
|
||||
key_str = "ESP_LE_KEY_PCSRK";
|
||||
break;
|
||||
case ESP_LE_KEY_PLK:
|
||||
key_str = "ESP_LE_KEY_PLK";
|
||||
break;
|
||||
case ESP_LE_KEY_LLK:
|
||||
key_str = "ESP_LE_KEY_LLK";
|
||||
break;
|
||||
case ESP_LE_KEY_LENC:
|
||||
key_str = "ESP_LE_KEY_LENC";
|
||||
break;
|
||||
case ESP_LE_KEY_LID:
|
||||
key_str = "ESP_LE_KEY_LID";
|
||||
break;
|
||||
case ESP_LE_KEY_LCSRK:
|
||||
key_str = "ESP_LE_KEY_LCSRK";
|
||||
break;
|
||||
default:
|
||||
key_str = "INVALID BLE KEY TYPE";
|
||||
break;
|
||||
}
|
||||
|
||||
return key_str;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BT_H_
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/BTHID.h
|
||||
701
main/include/BTHID.h
Normal file
701
main/include/BTHID.h
Normal file
@@ -0,0 +1,701 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: BTHID.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header file for the Bluetooth Keyboard Class.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// Jun 2022 - Updated with latest findings. Now checks the bonded list and opens
|
||||
// connections or scans for new devices if no connections exist.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BT_KEYBOARD_H_
|
||||
#define BT_KEYBOARD_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_hidh.h"
|
||||
#include "esp_hid_common.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "BT.h"
|
||||
|
||||
// Keyboard is a sub-class of BT which provides methods to setup BT for use by a keyboard.
|
||||
class BTHID : public BT {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Global constants
|
||||
#define MAX_KEYBOARD_DATA_BYTES 8
|
||||
#define MAX_CCONTROL_DATA_BYTES 3
|
||||
#define MAX_MOUSE_DATA_BYTES 7
|
||||
#define MAX_BT2PS2_MAP_ENTRIES 179
|
||||
#define MAX_BTMEDIA2PS2_MAP_ENTRIES 8
|
||||
|
||||
// LED's
|
||||
#define BT_LED_NUMLOCK 0x01
|
||||
#define BT_LED_CAPSLOCK 0x02
|
||||
#define BT_LED_SCROLLLOCK 0x04
|
||||
|
||||
// Control keys.
|
||||
#define BT_NONE 0x0000
|
||||
#define BT_CTRL_LEFT 0x0001
|
||||
#define BT_SHIFT_LEFT 0x0002
|
||||
#define BT_ALT_LEFT 0x0004
|
||||
#define BT_GUI_LEFT 0x0008
|
||||
#define BT_CTRL_RIGHT 0x0010
|
||||
#define BT_SHIFT_RIGHT 0x0020
|
||||
#define BT_ALT_RIGHT 0x0040
|
||||
#define BT_GUI_RIGHT 0x0080
|
||||
#define BT_CAPS_LOCK 0x0100
|
||||
#define BT_NUM_LOCK 0x0200
|
||||
#define BT_SCROLL_LOCK 0x0400
|
||||
#define BT_DUPLICATE 0xFFFF // Duplicate BT flags onto PS/2 flags.
|
||||
|
||||
#define BT_PS2_FUNCTION 0x01
|
||||
#define BT_PS2_GUI 0x02
|
||||
#define BT_PS2_ALT_GR 0x04
|
||||
#define BT_PS2_ALT 0x08
|
||||
#define BT_PS2_CAPS 0x10
|
||||
#define BT_PS2_CTRL 0x20
|
||||
#define BT_PS2_SHIFT 0x40
|
||||
#define BT_PS2_BREAK 0x80
|
||||
|
||||
#define BT_KEY_NONE 0x00 // No key pressed
|
||||
#define BT_KEY_ERR_OVF 0x01 // Keyboard Error Roll Over
|
||||
// 0x02 // Keyboard POST Fail
|
||||
// 0x03 // Keyboard Error Undefined
|
||||
#define BT_KEY_A 0x04 // Keyboard a and A
|
||||
#define BT_KEY_B 0x05 // Keyboard b and B
|
||||
#define BT_KEY_C 0x06 // Keyboard c and C
|
||||
#define BT_KEY_D 0x07 // Keyboard d and D
|
||||
#define BT_KEY_E 0x08 // Keyboard e and E
|
||||
#define BT_KEY_F 0x09 // Keyboard f and F
|
||||
#define BT_KEY_G 0x0a // Keyboard g and G
|
||||
#define BT_KEY_H 0x0b // Keyboard h and H
|
||||
#define BT_KEY_I 0x0c // Keyboard i and I
|
||||
#define BT_KEY_J 0x0d // Keyboard j and J
|
||||
#define BT_KEY_K 0x0e // Keyboard k and K
|
||||
#define BT_KEY_L 0x0f // Keyboard l and L
|
||||
#define BT_KEY_M 0x10 // Keyboard m and M
|
||||
#define BT_KEY_N 0x11 // Keyboard n and N
|
||||
#define BT_KEY_O 0x12 // Keyboard o and O
|
||||
#define BT_KEY_P 0x13 // Keyboard p and P
|
||||
#define BT_KEY_Q 0x14 // Keyboard q and Q
|
||||
#define BT_KEY_R 0x15 // Keyboard r and R
|
||||
#define BT_KEY_S 0x16 // Keyboard s and S
|
||||
#define BT_KEY_T 0x17 // Keyboard t and T
|
||||
#define BT_KEY_U 0x18 // Keyboard u and U
|
||||
#define BT_KEY_V 0x19 // Keyboard v and V
|
||||
#define BT_KEY_W 0x1a // Keyboard w and W
|
||||
#define BT_KEY_X 0x1b // Keyboard x and X
|
||||
#define BT_KEY_Y 0x1c // Keyboard y and Y
|
||||
#define BT_KEY_Z 0x1d // Keyboard z and Z
|
||||
|
||||
#define BT_KEY_1 0x1e // Keyboard 1 and !
|
||||
#define BT_KEY_2 0x1f // Keyboard 2 and @
|
||||
#define BT_KEY_3 0x20 // Keyboard 3 and #
|
||||
#define BT_KEY_4 0x21 // Keyboard 4 and $
|
||||
#define BT_KEY_5 0x22 // Keyboard 5 and %
|
||||
#define BT_KEY_6 0x23 // Keyboard 6 and ^
|
||||
#define BT_KEY_7 0x24 // Keyboard 7 and &
|
||||
#define BT_KEY_8 0x25 // Keyboard 8 and *
|
||||
#define BT_KEY_9 0x26 // Keyboard 9 and (
|
||||
#define BT_KEY_0 0x27 // Keyboard 0 and )
|
||||
|
||||
#define BT_KEY_ENTER 0x28 // Keyboard Return (ENTER)
|
||||
#define BT_KEY_ESC 0x29 // Keyboard ESCAPE
|
||||
#define BT_KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace)
|
||||
#define BT_KEY_TAB 0x2b // Keyboard Tab
|
||||
#define BT_KEY_SPACE 0x2c // Keyboard Spacebar
|
||||
#define BT_KEY_MINUS 0x2d // Keyboard - and _
|
||||
#define BT_KEY_EQUAL 0x2e // Keyboard = and +
|
||||
#define BT_KEY_LEFTBRACE 0x2f // Keyboard [ and {
|
||||
#define BT_KEY_RIGHTBRACE 0x30 // Keyboard ] and }
|
||||
#define BT_KEY_BACKSLASH 0x31 // Keyboard \ and |
|
||||
#define BT_KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~
|
||||
#define BT_KEY_SEMICOLON 0x33 // Keyboard ; and :
|
||||
#define BT_KEY_APOSTROPHE 0x34 // Keyboard ' and "
|
||||
#define BT_KEY_GRAVE 0x35 // Keyboard ` and ~
|
||||
#define BT_KEY_COMMA 0x36 // Keyboard , and <
|
||||
#define BT_KEY_DOT 0x37 // Keyboard . and >
|
||||
#define BT_KEY_SLASH 0x38 // Keyboard / and ?
|
||||
#define BT_KEY_CAPSLOCK 0x39 // Keyboard Caps Lock
|
||||
|
||||
#define BT_KEY_F1 0x3a // Keyboard F1
|
||||
#define BT_KEY_F2 0x3b // Keyboard F2
|
||||
#define BT_KEY_F3 0x3c // Keyboard F3
|
||||
#define BT_KEY_F4 0x3d // Keyboard F4
|
||||
#define BT_KEY_F5 0x3e // Keyboard F5
|
||||
#define BT_KEY_F6 0x3f // Keyboard F6
|
||||
#define BT_KEY_F7 0x40 // Keyboard F7
|
||||
#define BT_KEY_F8 0x41 // Keyboard F8
|
||||
#define BT_KEY_F9 0x42 // Keyboard F9
|
||||
#define BT_KEY_F10 0x43 // Keyboard F10
|
||||
#define BT_KEY_F11 0x44 // Keyboard F11
|
||||
#define BT_KEY_F12 0x45 // Keyboard F12
|
||||
|
||||
#define BT_KEY_SYSRQ 0x46 // Keyboard Print Screen
|
||||
#define BT_KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock
|
||||
#define BT_KEY_PAUSE 0x48 // Keyboard Pause
|
||||
#define BT_KEY_INSERT 0x49 // Keyboard Insert
|
||||
#define BT_KEY_HOME 0x4a // Keyboard Home
|
||||
#define BT_KEY_PAGEUP 0x4b // Keyboard Page Up
|
||||
#define BT_KEY_DELETE 0x4c // Keyboard Delete Forward
|
||||
#define BT_KEY_END 0x4d // Keyboard End
|
||||
#define BT_KEY_PAGEDOWN 0x4e // Keyboard Page Down
|
||||
#define BT_KEY_RIGHT 0x4f // Keyboard Right Arrow
|
||||
#define BT_KEY_LEFT 0x50 // Keyboard Left Arrow
|
||||
#define BT_KEY_DOWN 0x51 // Keyboard Down Arrow
|
||||
#define BT_KEY_UP 0x52 // Keyboard Up Arrow
|
||||
|
||||
#define BT_KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear
|
||||
#define BT_KEY_KPSLASH 0x54 // Keypad /
|
||||
#define BT_KEY_KPASTERISK 0x55 // Keypad *
|
||||
#define BT_KEY_KPMINUS 0x56 // Keypad -
|
||||
#define BT_KEY_KPPLUS 0x57 // Keypad +
|
||||
#define BT_KEY_KPENTER 0x58 // Keypad ENTER
|
||||
#define BT_KEY_KP1 0x59 // Keypad 1 and End
|
||||
#define BT_KEY_KP2 0x5a // Keypad 2 and Down Arrow
|
||||
#define BT_KEY_KP3 0x5b // Keypad 3 and PageDn
|
||||
#define BT_KEY_KP4 0x5c // Keypad 4 and Left Arrow
|
||||
#define BT_KEY_KP5 0x5d // Keypad 5
|
||||
#define BT_KEY_KP6 0x5e // Keypad 6 and Right Arrow
|
||||
#define BT_KEY_KP7 0x5f // Keypad 7 and Home
|
||||
#define BT_KEY_KP8 0x60 // Keypad 8 and Up Arrow
|
||||
#define BT_KEY_KP9 0x61 // Keypad 9 and Page Up
|
||||
#define BT_KEY_KP0 0x62 // Keypad 0 and Insert
|
||||
#define BT_KEY_KPDOT 0x63 // Keypad . and Delete
|
||||
|
||||
#define BT_KEY_102ND 0x64 // Keyboard Non-US \ and |
|
||||
#define BT_KEY_COMPOSE 0x65 // Keyboard Application
|
||||
#define BT_KEY_POWER 0x66 // Keyboard Power
|
||||
#define BT_KEY_KPEQUAL 0x67 // Keypad =
|
||||
|
||||
#define BT_KEY_F13 0x68 // Keyboard F13
|
||||
#define BT_KEY_F14 0x69 // Keyboard F14
|
||||
#define BT_KEY_F15 0x6a // Keyboard F15
|
||||
#define BT_KEY_F16 0x6b // Keyboard F16
|
||||
#define BT_KEY_F17 0x6c // Keyboard F17
|
||||
#define BT_KEY_F18 0x6d // Keyboard F18
|
||||
#define BT_KEY_F19 0x6e // Keyboard F19
|
||||
#define BT_KEY_F20 0x6f // Keyboard F20
|
||||
#define BT_KEY_F21 0x70 // Keyboard F21
|
||||
#define BT_KEY_F22 0x71 // Keyboard F22
|
||||
#define BT_KEY_F23 0x72 // Keyboard F23
|
||||
#define BT_KEY_F24 0x73 // Keyboard F24
|
||||
|
||||
#define BT_KEY_OPEN 0x74 // Keyboard Execute
|
||||
#define BT_KEY_HELP 0x75 // Keyboard Help
|
||||
#define BT_KEY_PROPS 0x76 // Keyboard Menu
|
||||
#define BT_KEY_FRONT 0x77 // Keyboard Select
|
||||
#define BT_KEY_STOP 0x78 // Keyboard Stop
|
||||
#define BT_KEY_AGAIN 0x79 // Keyboard Again
|
||||
#define BT_KEY_UNDO 0x7a // Keyboard Undo
|
||||
#define BT_KEY_CUT 0x7b // Keyboard Cut
|
||||
#define BT_KEY_COPY 0x7c // Keyboard Copy
|
||||
#define BT_KEY_PASTE 0x7d // Keyboard Paste
|
||||
#define BT_KEY_FIND 0x7e // Keyboard Find
|
||||
#define BT_KEY_MUTE 0x7f // Keyboard Mute
|
||||
#define BT_KEY_VOLUMEUP 0x80 // Keyboard Volume Up
|
||||
#define BT_KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down
|
||||
// 0x82 Keyboard Locking Caps Lock
|
||||
// 0x83 Keyboard Locking Num Lock
|
||||
// 0x84 Keyboard Locking Scroll Lock
|
||||
#define BT_KEY_KPCOMMA 0x85 // Keypad Comma
|
||||
// 0x86 Keypad Equal Sign
|
||||
#define BT_KEY_RO 0x87 // Keyboard International1
|
||||
#define BT_KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2
|
||||
#define BT_KEY_YEN 0x89 // Keyboard International3
|
||||
#define BT_KEY_HENKAN 0x8a // Keyboard International4
|
||||
#define BT_KEY_MUHENKAN 0x8b // Keyboard International5
|
||||
#define BT_KEY_KPJPCOMMA 0x8c // Keyboard International6
|
||||
// 0x8d Keyboard International7
|
||||
// 0x8e Keyboard International8
|
||||
// 0x8f Keyboard International9
|
||||
#define BT_KEY_HANGEUL 0x90 // Keyboard LANG1
|
||||
#define BT_KEY_HANJA 0x91 // Keyboard LANG2
|
||||
#define BT_KEY_KATAKANA 0x92 // Keyboard LANG3
|
||||
#define BT_KEY_HIRAGANA 0x93 // Keyboard LANG4
|
||||
#define BT_KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5
|
||||
// 0x95 Keyboard LANG6
|
||||
// 0x96 Keyboard LANG7
|
||||
// 0x97 Keyboard LANG8
|
||||
// 0x98 Keyboard LANG9
|
||||
// 0x99 Keyboard Alternate Erase
|
||||
// 0x9a Keyboard SysReq/Attention
|
||||
// 0x9b Keyboard Cancel
|
||||
// 0x9c Keyboard Clear
|
||||
// 0x9d Keyboard Prior
|
||||
// 0x9e Keyboard Return
|
||||
// 0x9f Keyboard Separator
|
||||
// 0xa0 Keyboard Out
|
||||
// 0xa1 Keyboard Oper
|
||||
// 0xa2 Keyboard Clear/Again
|
||||
// 0xa3 Keyboard CrSel/Props
|
||||
// 0xa4 Keyboard ExSel
|
||||
|
||||
// 0xb0 Keypad 00
|
||||
// 0xb1 Keypad 000
|
||||
// 0xb2 Thousands Separator
|
||||
// 0xb3 Decimal Separator
|
||||
// 0xb4 Currency Unit
|
||||
// 0xb5 Currency Sub-unit
|
||||
#define BT_KEY_KPLEFTPAREN 0xb6 // Keypad (
|
||||
#define BT_KEY_KPRIGHTPAREN 0xb7 // Keypad )
|
||||
// 0xb8 Keypad {
|
||||
// 0xb9 Keypad }
|
||||
// 0xba Keypad Tab
|
||||
// 0xbb Keypad Backspace
|
||||
// 0xbc Keypad A
|
||||
// 0xbd Keypad B
|
||||
// 0xbe Keypad C
|
||||
// 0xbf Keypad D
|
||||
// 0xc0 Keypad E
|
||||
// 0xc1 Keypad F
|
||||
// 0xc2 Keypad XOR
|
||||
// 0xc3 Keypad ^
|
||||
// 0xc4 Keypad %
|
||||
// 0xc5 Keypad <
|
||||
// 0xc6 Keypad >
|
||||
// 0xc7 Keypad &
|
||||
// 0xc8 Keypad &&
|
||||
// 0xc9 Keypad |
|
||||
// 0xca Keypad ||
|
||||
// 0xcb Keypad :
|
||||
// 0xcc Keypad #
|
||||
// 0xcd Keypad Space
|
||||
// 0xce Keypad @
|
||||
// 0xcf Keypad !
|
||||
// 0xd0 Keypad Memory Store
|
||||
// 0xd1 Keypad Memory Recall
|
||||
// 0xd2 Keypad Memory Clear
|
||||
// 0xd3 Keypad Memory Add
|
||||
// 0xd4 Keypad Memory Subtract
|
||||
// 0xd5 Keypad Memory Multiply
|
||||
// 0xd6 Keypad Memory Divide
|
||||
// 0xd7 Keypad +/-
|
||||
// 0xd8 Keypad Clear
|
||||
// 0xd9 Keypad Clear Entry
|
||||
// 0xda Keypad Binary
|
||||
// 0xdb Keypad Octal
|
||||
// 0xdc Keypad Decimal
|
||||
// 0xdd Keypad Hexadecimal
|
||||
|
||||
#define BT_KEY_LEFTCTRL 0xe0 // Keyboard Left Control
|
||||
#define BT_KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift
|
||||
#define BT_KEY_LEFTALT 0xe2 // Keyboard Left Alt
|
||||
#define BT_KEY_LEFTMETA 0xe3 // Keyboard Left GUI
|
||||
#define BT_KEY_RIGHTCTRL 0xe4 // Keyboard Right Control
|
||||
#define BT_KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift
|
||||
#define BT_KEY_RIGHTALT 0xe6 // Keyboard Right Alt
|
||||
#define BT_KEY_RIGHTMETA 0xe7 // Keyboard Right GUI
|
||||
|
||||
#define BT_KEY_MEDIA_PLAYPAUSE 0xe8
|
||||
#define BT_KEY_MEDIA_STOPCD 0xe9
|
||||
#define BT_KEY_MEDIA_PREVIOUSSONG 0xea
|
||||
#define BT_KEY_MEDIA_NEXTSONG 0xeb
|
||||
#define BT_KEY_MEDIA_EJECTCD 0xec
|
||||
#define BT_KEY_MEDIA_VOLUMEUP 0xed
|
||||
#define BT_KEY_MEDIA_VOLUMEDOWN 0xee
|
||||
#define BT_KEY_MEDIA_MUTE 0xef
|
||||
#define BT_KEY_MEDIA_WWW 0xf0
|
||||
#define BT_KEY_MEDIA_BACK 0xf1
|
||||
#define BT_KEY_MEDIA_FORWARD 0xf2
|
||||
#define BT_KEY_MEDIA_STOP 0xf3
|
||||
#define BT_KEY_MEDIA_FIND 0xf4
|
||||
#define BT_KEY_MEDIA_SCROLLUP 0xf5
|
||||
#define BT_KEY_MEDIA_SCROLLDOWN 0xf6
|
||||
#define BT_KEY_MEDIA_EDIT 0xf7
|
||||
#define BT_KEY_MEDIA_SLEEP 0xf8
|
||||
#define BT_KEY_MEDIA_COFFEE 0xf9
|
||||
#define BT_KEY_MEDIA_REFRESH 0xfa
|
||||
#define BT_KEY_MEDIA_CALC 0xfb
|
||||
|
||||
// Media key definition. On the ESP module a seperate usage type, CCONTROL is created for media keys and it delivers a 24bit word, each bit signifying a key.
|
||||
#define BT_MEDIA_SEARCH 0x00200000
|
||||
#define BT_MEDIA_HOME 0x00080000
|
||||
#define BT_MEDIA_BRIGHTNESS_UP 0x00004000
|
||||
#define BT_MEDIA_BRIGHTNESS_DOWN 0x00008000
|
||||
#define BT_MEDIA_MUTE 0x00000040
|
||||
#define BT_MEDIA_VOL_DOWN 0x00000020
|
||||
#define BT_MEDIA_VOL_UP 0x00000010
|
||||
#define BT_MEDIA_TRACK_PREV 0x00000001
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2_FLG_NONE 0x00 // No keys active = 0
|
||||
#define PS2_FLG_SHIFT PS2_SHIFT >> 8 // Shift Key active = 1
|
||||
#define PS2_FLG_CTRL PS2_CTRL >> 8 // Ctrl Key active = 1
|
||||
#define PS2_FLG_CAPS PS2_CAPS >> 8 // CAPS active = 1
|
||||
#define PS2_FLG_ALT PS2_ALT >> 8 // ALT flag used as Right CTRL flag, active = 1
|
||||
#define PS2_FLG_ALTGR PS2_ALT_GR >> 8 // ALTGR active = 1
|
||||
#define PS2_FLG_GUI PS2_GUI >> 8 // GUI Key active = 1
|
||||
#define PS2_FLG_FUNC PS2_FUNCTION >> 8 // Special Function Keys active = 1
|
||||
#define PS2_FLG_BREAK PS2_BREAL >> 8 // BREAK Key active = 1
|
||||
|
||||
|
||||
public:
|
||||
|
||||
struct KeyInfo {
|
||||
uint8_t keys[MAX_KEYBOARD_DATA_BYTES];
|
||||
uint8_t length;
|
||||
bool cControl;
|
||||
esp_hidh_dev_t *hdlDev;
|
||||
};
|
||||
|
||||
// Prototypes.
|
||||
BTHID(void);
|
||||
virtual ~BTHID(void);
|
||||
bool setup(t_pairingHandler *handler);
|
||||
bool openDevice(esp_bd_addr_t bda, esp_hid_transport_t transport, esp_ble_addr_type_t addrType);
|
||||
bool closeDevice(esp_bd_addr_t bda);
|
||||
void checkBTDevices(void);
|
||||
bool setResolution(enum PS2Mouse::PS2_RESOLUTION resolution);
|
||||
bool setScaling(enum PS2Mouse::PS2_SCALING scaling);
|
||||
bool setSampleRate(enum PS2Mouse::PS2_SAMPLING rate);
|
||||
void processBTKeys(void);
|
||||
uint16_t getKey(uint32_t timeout = 0);
|
||||
|
||||
// Method to register an object method for callback with context.
|
||||
template<typename A, typename B>
|
||||
void setMouseDataCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
btHIDCtrl.ms.mouseDataCallback = bind(func_ptr, obj_ptr, 1, std::placeholders::_1);
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr char const * TAG = "BTHID";
|
||||
|
||||
// Structure to hold details of an active or post-active connection.
|
||||
typedef struct {
|
||||
esp_bd_addr_t bda;
|
||||
esp_hid_transport_t transport;
|
||||
esp_ble_addr_type_t addrType;
|
||||
esp_hid_usage_t usage;
|
||||
esp_hidh_dev_t *hidhDevHdl;
|
||||
uint32_t nextCheckTime;
|
||||
bool open;
|
||||
} t_activeDev;
|
||||
|
||||
// Structure to encapsulate a single key map from Bluetooth to PS/2.
|
||||
typedef struct {
|
||||
uint8_t btKeyCode;
|
||||
uint16_t btCtrl;
|
||||
uint8_t ps2KeyCode;
|
||||
uint16_t ps2Ctrl;
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[MAX_BT2PS2_MAP_ENTRIES];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to contain a media key map.
|
||||
typedef struct {
|
||||
uint32_t mediaKey; // 24bit Media key value.
|
||||
uint8_t ps2Key; // Equivalent PS/2 key for media key.
|
||||
uint16_t ps2Ctrl; // PS/2 translated control flags.
|
||||
} t_mediaMapEntry;
|
||||
|
||||
// Structure to encapsulate Media key mappings.
|
||||
typedef struct {
|
||||
t_mediaMapEntry kme[MAX_BTMEDIA2PS2_MAP_ENTRIES];
|
||||
} t_mediaKeyMap;
|
||||
|
||||
// Structure to maintain control variables.
|
||||
typedef struct {
|
||||
// Array of active devices which connect with the SharpKey.
|
||||
std::vector<t_activeDev> devices;
|
||||
|
||||
// Keyboard handling.
|
||||
struct {
|
||||
// Queues for storing data in the 2 processing stages.
|
||||
xQueueHandle rawKeyQueue;
|
||||
xQueueHandle keyQueue;
|
||||
|
||||
uint8_t lastKeys[MAX_KEYBOARD_DATA_BYTES]; // Required to generate a PS/2 break event when a key is released.
|
||||
uint32_t lastMediaKey; // Required to detect changes in the media control keys, ie. release.
|
||||
uint16_t btFlags; // Bluetooth control flags.
|
||||
uint16_t ps2Flags; // PS/2 translated control flags.
|
||||
uint8_t statusLED; // Keyboard LED state.
|
||||
t_keyMapEntry *kme; // Pointer to the mapping array.
|
||||
t_mediaMapEntry *kmeMedia; // Pointer to the media key mapping array.
|
||||
int kmeRows; // Number of entries in the BT to PS/2 mapping table.
|
||||
int kmeMediaRows; // Number of entries in the BT to PS/2 media key mapping table.
|
||||
} kbd;
|
||||
|
||||
// Mouse handling.
|
||||
struct {
|
||||
int resolution; // PS/2 compatible resolution (pixels per mm) setting.
|
||||
int scaling; // PS/2 compatible scaling (1:1 or 2:1).
|
||||
int sampleRate; // PS/2 compatible sample rate (10 .. 200).
|
||||
int xDivisor; // Divisor on the X plane to scale down the 12bit BT resolution.
|
||||
int yDivisor; // Divisor on the Y plane to scale down the 12bit BT resolution.
|
||||
|
||||
// Callback for streaming processed mouse data to HID handler.
|
||||
std::function<void(PS2Mouse::MouseData)> mouseDataCallback;
|
||||
} ms;
|
||||
|
||||
BTHID *pThis;
|
||||
} t_btHIDCtrl;
|
||||
|
||||
// All control variables are stored in a struct for ease of reference.
|
||||
t_btHIDCtrl btHIDCtrl;
|
||||
|
||||
// Prototypes.
|
||||
static void hidh_callback(void * handler_args, esp_event_base_t base, int32_t id, void * event_data);
|
||||
void pushKeyToFIFO(esp_hid_usage_t src, esp_hidh_dev_t *hdlDev, uint8_t *keys, uint8_t size);
|
||||
void setStatusLED(esp_hidh_dev_t *dev, uint8_t led);
|
||||
void clearStatusLED(esp_hidh_dev_t *dev, uint8_t led);
|
||||
uint16_t mapBTMediaToPS2(uint32_t key);
|
||||
uint16_t mapBTtoPS2(uint8_t key);
|
||||
inline uint32_t milliSeconds(void)
|
||||
{
|
||||
return( (uint32_t) (clock() ) );
|
||||
}
|
||||
|
||||
// Mapping for Media keys. ESP module seperates them but not properly, some media keys are sent as normal key scancodes others as control key bit maps.
|
||||
// Hence two mapping tables, one for normal scancodes and one for media codes.
|
||||
t_mediaKeyMap MediaKeyToPS2 = {
|
||||
{
|
||||
{ BT_MEDIA_SEARCH, PS2_KEY_WEB_SEARCH, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_HOME, PS2_KEY_WEB_HOME, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_BRIGHTNESS_UP, PS2_KEY_WEB_FORWARD, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_BRIGHTNESS_DOWN, PS2_KEY_WEB_BACK, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_MUTE, PS2_KEY_MUTE, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_VOL_DOWN, PS2_KEY_VOL_DN, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_VOL_UP, PS2_KEY_VOL_UP, PS2_FLG_NONE, },
|
||||
{ BT_MEDIA_TRACK_PREV, PS2_KEY_PREV_TR, PS2_FLG_NONE, },
|
||||
}};
|
||||
|
||||
// Mapping table between BT Keyboard Scan Codes and PS/2 Keyboard Scan Codes.
|
||||
//
|
||||
t_keyMap BTKeyToPS2 = {
|
||||
{
|
||||
// Bluetooth Key Bluetooth Control, PS/2 Key PS/2 Control,
|
||||
{ BT_KEY_A, BT_NONE, PS2_KEY_A, PS2_FLG_NONE, },
|
||||
{ BT_KEY_B, BT_NONE, PS2_KEY_B, PS2_FLG_NONE, },
|
||||
{ BT_KEY_C, BT_NONE, PS2_KEY_C, PS2_FLG_NONE, },
|
||||
{ BT_KEY_D, BT_NONE, PS2_KEY_D, PS2_FLG_NONE, },
|
||||
{ BT_KEY_E, BT_NONE, PS2_KEY_E, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F, BT_NONE, PS2_KEY_F, PS2_FLG_NONE, },
|
||||
{ BT_KEY_G, BT_NONE, PS2_KEY_G, PS2_FLG_NONE, },
|
||||
{ BT_KEY_H, BT_NONE, PS2_KEY_H, PS2_FLG_NONE, },
|
||||
{ BT_KEY_I, BT_NONE, PS2_KEY_I, PS2_FLG_NONE, },
|
||||
{ BT_KEY_J, BT_NONE, PS2_KEY_J, PS2_FLG_NONE, },
|
||||
{ BT_KEY_K, BT_NONE, PS2_KEY_K, PS2_FLG_NONE, },
|
||||
{ BT_KEY_L, BT_NONE, PS2_KEY_L, PS2_FLG_NONE, },
|
||||
{ BT_KEY_M, BT_NONE, PS2_KEY_M, PS2_FLG_NONE, },
|
||||
{ BT_KEY_N, BT_NONE, PS2_KEY_N, PS2_FLG_NONE, },
|
||||
{ BT_KEY_O, BT_NONE, PS2_KEY_O, PS2_FLG_NONE, },
|
||||
{ BT_KEY_P, BT_NONE, PS2_KEY_P, PS2_FLG_NONE, },
|
||||
{ BT_KEY_Q, BT_NONE, PS2_KEY_Q, PS2_FLG_NONE, },
|
||||
{ BT_KEY_R, BT_NONE, PS2_KEY_R, PS2_FLG_NONE, },
|
||||
{ BT_KEY_S, BT_NONE, PS2_KEY_S, PS2_FLG_NONE, },
|
||||
{ BT_KEY_T, BT_NONE, PS2_KEY_T, PS2_FLG_NONE, },
|
||||
{ BT_KEY_U, BT_NONE, PS2_KEY_U, PS2_FLG_NONE, },
|
||||
{ BT_KEY_V, BT_NONE, PS2_KEY_V, PS2_FLG_NONE, },
|
||||
{ BT_KEY_W, BT_NONE, PS2_KEY_W, PS2_FLG_NONE, },
|
||||
{ BT_KEY_X, BT_NONE, PS2_KEY_X, PS2_FLG_NONE, },
|
||||
{ BT_KEY_Y, BT_NONE, PS2_KEY_Y, PS2_FLG_NONE, },
|
||||
{ BT_KEY_Z, BT_NONE, PS2_KEY_Z, PS2_FLG_NONE, },
|
||||
{ BT_KEY_1, BT_NONE, PS2_KEY_1, PS2_FLG_NONE, },
|
||||
{ BT_KEY_2, BT_NONE, PS2_KEY_2, PS2_FLG_NONE, },
|
||||
{ BT_KEY_3, BT_NONE, PS2_KEY_3, PS2_FLG_NONE, },
|
||||
{ BT_KEY_4, BT_NONE, PS2_KEY_4, PS2_FLG_NONE, },
|
||||
{ BT_KEY_5, BT_NONE, PS2_KEY_5, PS2_FLG_NONE, },
|
||||
{ BT_KEY_6, BT_NONE, PS2_KEY_6, PS2_FLG_NONE, },
|
||||
{ BT_KEY_7, BT_NONE, PS2_KEY_7, PS2_FLG_NONE, },
|
||||
{ BT_KEY_8, BT_NONE, PS2_KEY_8, PS2_FLG_NONE, },
|
||||
{ BT_KEY_9, BT_NONE, PS2_KEY_9, PS2_FLG_NONE, },
|
||||
{ BT_KEY_0, BT_NONE, PS2_KEY_0, PS2_FLG_NONE, },
|
||||
{ BT_KEY_ENTER, BT_NONE, PS2_KEY_ENTER, PS2_FLG_NONE, },
|
||||
{ BT_KEY_ESC, BT_NONE, PS2_KEY_ESC, PS2_FLG_NONE, },
|
||||
{ BT_KEY_BACKSPACE, BT_NONE, PS2_KEY_BS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_TAB, BT_NONE, PS2_KEY_TAB, PS2_FLG_NONE, },
|
||||
{ BT_KEY_SPACE, BT_NONE, PS2_KEY_SPACE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MINUS, BT_NONE, PS2_KEY_MINUS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_EQUAL, BT_NONE, PS2_KEY_EQUAL, PS2_FLG_NONE, },
|
||||
{ BT_KEY_LEFTBRACE, BT_NONE, PS2_KEY_OPEN_SQ, PS2_FLG_NONE, },
|
||||
{ BT_KEY_RIGHTBRACE, BT_NONE, PS2_KEY_CLOSE_SQ, PS2_FLG_NONE, },
|
||||
{ BT_KEY_BACKSLASH, BT_NONE, PS2_KEY_BACK, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HASHTILDE, BT_NONE, PS2_KEY_HASH, PS2_FLG_NONE, },
|
||||
{ BT_KEY_SEMICOLON, BT_NONE, PS2_KEY_SEMI, PS2_FLG_NONE, },
|
||||
{ BT_KEY_APOSTROPHE, BT_NONE, PS2_KEY_APOS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_GRAVE, BT_NONE, PS2_KEY_BTICK, PS2_FLG_NONE, },
|
||||
{ BT_KEY_COMMA, BT_NONE, PS2_KEY_COMMA, PS2_FLG_NONE, },
|
||||
{ BT_KEY_DOT, BT_NONE, PS2_KEY_DOT, PS2_FLG_NONE, },
|
||||
{ BT_KEY_SLASH, BT_NONE, PS2_KEY_DIV, PS2_FLG_NONE, },
|
||||
{ BT_KEY_CAPSLOCK, BT_NONE, PS2_KEY_CAPS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F1, BT_NONE, PS2_KEY_F1, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F2, BT_NONE, PS2_KEY_F2, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F3, BT_NONE, PS2_KEY_F3, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F4, BT_NONE, PS2_KEY_F4, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F5, BT_NONE, PS2_KEY_F5, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F6, BT_NONE, PS2_KEY_F6, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F7, BT_NONE, PS2_KEY_F7, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F8, BT_NONE, PS2_KEY_F8, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F9, BT_NONE, PS2_KEY_F9, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F10, BT_NONE, PS2_KEY_F10, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F11, BT_NONE, PS2_KEY_F11, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F12, BT_NONE, PS2_KEY_F12, PS2_FLG_NONE, },
|
||||
{ BT_KEY_SYSRQ, BT_NONE, PS2_KEY_PRTSCR, PS2_FLG_NONE, },
|
||||
{ BT_KEY_SCROLLLOCK, BT_NONE, PS2_KEY_SCROLL, PS2_FLG_NONE, },
|
||||
{ BT_KEY_PAUSE, BT_NONE, PS2_KEY_PAUSE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_INSERT, BT_NONE, PS2_KEY_INSERT, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HOME, BT_NONE, PS2_KEY_HOME, PS2_FLG_NONE, },
|
||||
{ BT_KEY_PAGEUP, BT_NONE, PS2_KEY_PGUP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_DELETE, BT_NONE, PS2_KEY_DELETE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_END, BT_NONE, PS2_KEY_END, PS2_FLG_NONE, },
|
||||
{ BT_KEY_PAGEDOWN, BT_NONE, PS2_KEY_PGDN, PS2_FLG_NONE, },
|
||||
{ BT_KEY_RIGHT, BT_NONE, PS2_KEY_R_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_LEFT, BT_NONE, PS2_KEY_L_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_DOWN, BT_NONE, PS2_KEY_DN_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_UP, BT_NONE, PS2_KEY_UP_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_NUMLOCK, BT_NONE, PS2_KEY_NUM, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPSLASH, BT_NONE, PS2_KEY_KP_DIV, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPASTERISK, BT_NONE, PS2_KEY_KP_TIMES, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPMINUS, BT_NONE, PS2_KEY_KP_MINUS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPPLUS, BT_NONE, PS2_KEY_KP_PLUS, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPENTER, BT_NONE, PS2_KEY_KP_ENTER, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP1, BT_NUM_LOCK, PS2_KEY_KP1, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP2, BT_NUM_LOCK, PS2_KEY_KP2, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP3, BT_NUM_LOCK, PS2_KEY_KP3, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP4, BT_NUM_LOCK, PS2_KEY_KP4, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP5, BT_NUM_LOCK, PS2_KEY_KP5, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP6, BT_NUM_LOCK, PS2_KEY_KP6, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP7, BT_NUM_LOCK, PS2_KEY_KP7, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP8, BT_NUM_LOCK, PS2_KEY_KP8, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP9, BT_NUM_LOCK, PS2_KEY_KP9, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP0, BT_NUM_LOCK, PS2_KEY_KP0, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPDOT, BT_NUM_LOCK, PS2_KEY_KP_DOT, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP1, BT_NONE, PS2_KEY_END, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP2, BT_NONE, PS2_KEY_DN_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP3, BT_NONE, PS2_KEY_PGDN, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP4, BT_NONE, PS2_KEY_L_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP5, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP6, BT_NONE, PS2_KEY_R_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP7, BT_NONE, PS2_KEY_HOME, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP8, BT_NONE, PS2_KEY_UP_ARROW, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP9, BT_NONE, PS2_KEY_PGUP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KP0, BT_NONE, PS2_KEY_INSERT, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPDOT, BT_NONE, PS2_KEY_DELETE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_102ND, BT_NONE, PS2_KEY_BACK, PS2_FLG_NONE, },
|
||||
{ BT_KEY_COMPOSE, BT_NONE, PS2_KEY_MENU, PS2_FLG_NONE, },
|
||||
{ BT_KEY_POWER, BT_NONE, PS2_KEY_POWER, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPEQUAL, BT_NONE, PS2_KEY_KP_EQUAL, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F13, BT_NONE, PS2_KEY_F13, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F14, BT_NONE, PS2_KEY_F14, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F15, BT_NONE, PS2_KEY_F15, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F16, BT_NONE, PS2_KEY_F16, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F17, BT_NONE, PS2_KEY_F17, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F18, BT_NONE, PS2_KEY_F18, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F19, BT_NONE, PS2_KEY_F19, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F20, BT_NONE, PS2_KEY_F20, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F21, BT_NONE, PS2_KEY_F21, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F22, BT_NONE, PS2_KEY_F22, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F23, BT_NONE, PS2_KEY_F23, PS2_FLG_NONE, },
|
||||
{ BT_KEY_F24, BT_NONE, PS2_KEY_F24, PS2_FLG_NONE, },
|
||||
{ BT_KEY_OPEN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HELP, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_PROPS, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_FRONT, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_STOP, BT_NONE, PS2_KEY_STOP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_AGAIN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_UNDO, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_CUT, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_COPY, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_PASTE, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_FIND, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MUTE, BT_NONE, PS2_KEY_MUTE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_VOLUMEUP, BT_NONE, PS2_KEY_VOL_UP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_VOLUMEDOWN, BT_NONE, PS2_KEY_VOL_DN, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPCOMMA, BT_NONE, PS2_KEY_KP_COMMA, PS2_FLG_NONE, },
|
||||
{ BT_KEY_RO, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KATAKANAHIRAGANA, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_YEN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HENKAN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MUHENKAN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPJPCOMMA, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HANGEUL, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HANJA, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KATAKANA, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_HIRAGANA, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_ZENKAKUHANKAKU, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPLEFTPAREN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_KPRIGHTPAREN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
// Control keys.
|
||||
{ BT_KEY_LEFTCTRL, BT_NONE, PS2_KEY_L_CTRL, PS2_FLG_FUNC | PS2_FLG_CTRL, },
|
||||
{ BT_KEY_LEFTSHIFT, BT_NONE, PS2_KEY_L_SHIFT, PS2_FLG_FUNC | PS2_FLG_SHIFT, },
|
||||
{ BT_KEY_LEFTALT, BT_NONE, PS2_KEY_L_ALT, PS2_FLG_FUNC | PS2_FLG_ALT, },
|
||||
{ BT_KEY_LEFTMETA, BT_NONE, PS2_KEY_L_GUI, PS2_FLG_FUNC | PS2_FLG_GUI, },
|
||||
{ BT_KEY_RIGHTCTRL, BT_NONE, PS2_KEY_R_CTRL, PS2_FLG_FUNC | PS2_FLG_CTRL, },
|
||||
{ BT_KEY_RIGHTSHIFT, BT_NONE, PS2_KEY_R_SHIFT, PS2_FLG_FUNC | PS2_FLG_SHIFT, },
|
||||
{ BT_KEY_RIGHTALT, BT_NONE, PS2_KEY_R_ALT, PS2_FLG_FUNC | PS2_FLG_ALTGR, },
|
||||
{ BT_KEY_RIGHTMETA, BT_NONE, PS2_KEY_R_GUI, PS2_FLG_FUNC | PS2_FLG_NONE, },
|
||||
// Media keys
|
||||
{ BT_KEY_MEDIA_PLAYPAUSE, BT_NONE, PS2_KEY_PLAY, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_STOPCD, BT_NONE, PS2_KEY_STOP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_PREVIOUSSONG, BT_NONE, PS2_KEY_PREV_TR, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_NEXTSONG, BT_NONE, PS2_KEY_NEXT_TR, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_EJECTCD, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_VOLUMEUP, BT_NONE, PS2_KEY_VOL_UP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_VOLUMEDOWN, BT_NONE, PS2_KEY_VOL_DN, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_MUTE, BT_NONE, PS2_KEY_MUTE, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_WWW, BT_NONE, PS2_KEY_WEB_SEARCH, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_BACK, BT_NONE, PS2_KEY_WEB_BACK, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_FORWARD, BT_NONE, PS2_KEY_WEB_FORWARD, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_STOP, BT_NONE, PS2_KEY_WEB_STOP, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_FIND, BT_NONE, PS2_KEY_WEB_SEARCH, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_SCROLLUP, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_SCROLLDOWN, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_EDIT, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_SLEEP, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_COFFEE, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_REFRESH, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
{ BT_KEY_MEDIA_CALC, BT_NONE, 0x00, PS2_FLG_NONE, },
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // BT_KEYBOARD_H_
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/HID.h
|
||||
385
main/include/HID.h
Normal file
385
main/include/HID.h
Normal file
@@ -0,0 +1,385 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: HID.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: A HID Class definition, used to instantiate differing input device classes and
|
||||
// present a standard API.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to support Bluetooth keyboard and mouse. The mouse can be
|
||||
// a primary device or a secondary device for hosts which support
|
||||
// keyboard and mouse over one physical port.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef HID_H
|
||||
#define HID_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "BTHID.h"
|
||||
#include "LED.h"
|
||||
#include "SWITCH.h"
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Define a class which acts as the encapsulation object of many base classes which provide input device functionality.
|
||||
class HID {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define HID_VERSION 1.02
|
||||
#define HID_MOUSE_DATA_POLL_DELAY 10
|
||||
#define MAX_MOUSE_INACTIVITY_TIME 500 * HID_MOUSE_DATA_POLL_DELAY
|
||||
|
||||
// Categories of configuration possible with the mouse. These are used primarily with the web based UI for rendering selection choices.
|
||||
#define HID_MOUSE_HOST_SCALING_TYPE "host_scaling"
|
||||
#define HID_MOUSE_SCALING_TYPE "mouse_scaling"
|
||||
#define HID_MOUSE_RESOLUTION_TYPE "mouse_resolution"
|
||||
#define HID_MOUSE_SAMPLING_TYPE "mouse_sampling"
|
||||
|
||||
#define HID_MOUSE_HOST_SCALING_1_1_NAME "1:1"
|
||||
#define HID_MOUSE_HOST_SCALING_1_2_NAME "1:2"
|
||||
#define HID_MOUSE_HOST_SCALING_1_3_NAME "1:3"
|
||||
#define HID_MOUSE_HOST_SCALING_1_4_NAME "1:4"
|
||||
#define HID_MOUSE_HOST_SCALING_1_5_NAME "1:5"
|
||||
|
||||
// Names for the configuration value settings.
|
||||
#define HID_MOUSE_RESOLUTION_1_1_NAME "1 c/mm"
|
||||
#define HID_MOUSE_RESOLUTION_1_2_NAME "2 c/mm"
|
||||
#define HID_MOUSE_RESOLUTION_1_4_NAME "4 c/mm"
|
||||
#define HID_MOUSE_RESOLUTION_1_8_NAME "8 c/mm"
|
||||
#define HID_MOUSE_SCALING_1_1_NAME "1:1"
|
||||
#define HID_MOUSE_SCALING_2_1_NAME "2:1"
|
||||
#define HID_MOUSE_SAMPLE_RATE_10_NAME "10 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_20_NAME "20 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_40_NAME "40 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_60_NAME "60 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_80_NAME "80 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_100_NAME "100 S/s"
|
||||
#define HID_MOUSE_SAMPLE_RATE_200_NAME "200 S/s"
|
||||
|
||||
public:
|
||||
// Types of devices the HID class can support.
|
||||
enum HID_DEVICE_TYPES {
|
||||
HID_DEVICE_TYPE_KEYBOARD = 0x00,
|
||||
HID_DEVICE_TYPE_MOUSE = 0x01,
|
||||
HID_DEVICE_TYPE_BLUETOOTH = 0x02,
|
||||
};
|
||||
|
||||
// HID class can encapsulate many input device objects, only one at a time though. On startup the device is enumerated and then all
|
||||
// functionality serves the device object.
|
||||
enum HID_INPUT_DEVICE {
|
||||
HID_DEVICE_PS2_KEYBOARD = 0x00,
|
||||
HID_DEVICE_PS2_MOUSE = 0x01,
|
||||
HID_DEVICE_BLUETOOTH = 0x02,
|
||||
HID_DEVICE_BT_KEYBOARD = 0x03,
|
||||
HID_DEVICE_BT_MOUSE = 0x04
|
||||
};
|
||||
|
||||
// Scaling - The host receiving mouse data may have a different resolution to that of the mouse, so we use configurable host side scaling to compensate. The mouse data received
|
||||
// is scaled according to the enum setting.
|
||||
enum HID_MOUSE_HOST_SCALING {
|
||||
HID_MOUSE_HOST_SCALING_1_1 = 0x00,
|
||||
HID_MOUSE_HOST_SCALING_1_2 = 0x01,
|
||||
HID_MOUSE_HOST_SCALING_1_3 = 0x02,
|
||||
HID_MOUSE_HOST_SCALING_1_4 = 0x03,
|
||||
HID_MOUSE_HOST_SCALING_1_5 = 0x04,
|
||||
};
|
||||
|
||||
// Resolution - the mouse can digitize movement from 1mm to 1/8mm, the default being 1/4 (ie. 1mm = 4 counts). This allows configuration for a finer or rougher
|
||||
// tracking digitisation.
|
||||
enum HID_MOUSE_RESOLUTION {
|
||||
HID_MOUSE_RESOLUTION_1_1 = PS2Mouse::PS2_MOUSE_RESOLUTION_1_1,
|
||||
HID_MOUSE_RESOLUTION_1_2 = PS2Mouse::PS2_MOUSE_RESOLUTION_1_2,
|
||||
HID_MOUSE_RESOLUTION_1_4 = PS2Mouse::PS2_MOUSE_RESOLUTION_1_4,
|
||||
HID_MOUSE_RESOLUTION_1_8 = PS2Mouse::PS2_MOUSE_RESOLUTION_1_8,
|
||||
};
|
||||
|
||||
// Scaling - the mouse can provide linear (1:1 no scaling) or non liner (2:1 scaling) adaptation of the digitised data. This allows configuration for amplification of movements.
|
||||
enum HID_MOUSE_SCALING {
|
||||
HID_MOUSE_SCALING_1_1 = PS2Mouse::PS2_MOUSE_SCALING_1_1,
|
||||
HID_MOUSE_SCALING_2_1 = PS2Mouse::PS2_MOUSE_SCALING_2_1,
|
||||
};
|
||||
|
||||
// Sampling rate - the mouse, in streaming mode, the mouse sends with movement updates. This allows for finer or rougher digitisation of movements. The default is 100 samples per
|
||||
// second and the X68000 is fixed at 100 samples per second.
|
||||
enum HID_MOUSE_SAMPLING {
|
||||
HID_MOUSE_SAMPLE_RATE_10 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_10,
|
||||
HID_MOUSE_SAMPLE_RATE_20 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_20,
|
||||
HID_MOUSE_SAMPLE_RATE_40 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_40,
|
||||
HID_MOUSE_SAMPLE_RATE_60 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_60,
|
||||
HID_MOUSE_SAMPLE_RATE_80 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_80,
|
||||
HID_MOUSE_SAMPLE_RATE_100 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_100,
|
||||
HID_MOUSE_SAMPLE_RATE_200 = PS2Mouse::PS2_MOUSE_SAMPLE_RATE_200,
|
||||
};
|
||||
|
||||
// Suspend flag. When active, the interface components enter an idle state after completing there latest cycle.
|
||||
bool suspend = false;
|
||||
bool suspended = true;
|
||||
|
||||
// Element to store mouse data in a queue. The data is actual mouse movements, any control data and private data for the actual mouse is stripped.
|
||||
typedef struct {
|
||||
int16_t xPos;
|
||||
int16_t yPos;
|
||||
uint8_t status;
|
||||
uint8_t wheel;
|
||||
} t_mouseMessageElement;
|
||||
|
||||
// Prototypes.
|
||||
HID(enum HID_DEVICE_TYPES, NVS *hdlNVS, LED *hdlLED, SWITCH *hdlSWITCH);
|
||||
HID(NVS *hdlNVS);
|
||||
HID(void);
|
||||
virtual ~HID(void);
|
||||
bool isBluetooth(void);
|
||||
void enableBluetooth(void);
|
||||
void disableBluetooth(void);
|
||||
bool isSuspended(bool waitForSuspend);
|
||||
void suspendInterface(bool suspendIf);
|
||||
bool persistConfig(void);
|
||||
uint16_t read(void);
|
||||
void setMouseResolution(enum HID_MOUSE_RESOLUTION resolution);
|
||||
void setMouseHostScaling(enum HID_MOUSE_HOST_SCALING scaling);
|
||||
void setMouseScaling(enum HID_MOUSE_SCALING scaling);
|
||||
void setMouseSampleRate(enum HID_MOUSE_SAMPLING sampleRate);
|
||||
void btStartPairing(void);
|
||||
void btCancelPairing(void);
|
||||
|
||||
|
||||
// Method to register an object method for callback with context.
|
||||
template<typename A, typename B>
|
||||
void setDataCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
hidCtrl.dataCallback = bind(func_ptr, obj_ptr, std::placeholders::_1);
|
||||
}
|
||||
|
||||
// Method to suspend input device activity, yielding to the OS until suspend is cleared.
|
||||
inline virtual void yield(uint32_t delay)
|
||||
{
|
||||
// If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
if(this->suspend)
|
||||
{
|
||||
// Suspend the keyboard interface.
|
||||
if(hidCtrl.deviceType == HID_DEVICE_TYPE_KEYBOARD) { printf("SUSPEND\n"); ps2Keyboard->suspend(true); }
|
||||
this->suspended = true;
|
||||
|
||||
// Sleep while suspended.
|
||||
while(this->suspend)
|
||||
{
|
||||
vTaskDelay(100);
|
||||
}
|
||||
|
||||
// Release the keyboard interface.
|
||||
if(hidCtrl.deviceType == HID_DEVICE_TYPE_KEYBOARD) ps2Keyboard->suspend(false);
|
||||
this->suspended = false;
|
||||
} else
|
||||
// Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
{
|
||||
vTaskDelay(delay);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to see if the interface must enter suspend mode.
|
||||
//
|
||||
inline virtual bool suspendRequested(void)
|
||||
{
|
||||
return(this->suspend);
|
||||
}
|
||||
|
||||
// Helper method to identify the sub class, this is used in non volatile key management.
|
||||
// Warning: This method wont work if optimisation for size is enabled on the compiler.
|
||||
const char *getClassName(const std::string& prettyFunction)
|
||||
{
|
||||
// First find the CLASS :: METHOD seperation.
|
||||
size_t colons = prettyFunction.find("::");
|
||||
|
||||
// None, then this is not a class.
|
||||
if (colons == std::string::npos)
|
||||
return "::";
|
||||
|
||||
// Split out the class name.
|
||||
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
|
||||
size_t end = colons - begin;
|
||||
|
||||
// Return the name.
|
||||
return(prettyFunction.substr(begin,end).c_str());
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
// Method to return the class version number.
|
||||
virtual float version(void)
|
||||
{
|
||||
return(HID_VERSION);
|
||||
}
|
||||
|
||||
// Method to return the name of this class.
|
||||
virtual std::string ifName(void)
|
||||
{
|
||||
return(className);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
void init(const char *className, enum HID_DEVICE_TYPES deviceTypes);
|
||||
bool nvsPersistData(const char *key, void *pData, uint32_t size);
|
||||
bool nvsRetrieveData(const char *key, void *pData, uint32_t size);
|
||||
bool nvsCommitData(void);
|
||||
void checkKeyboard( void );
|
||||
bool checkPS2Keyboard( void );
|
||||
bool checkPS2Mouse( void );
|
||||
void checkMouse( void );
|
||||
void processPS2Mouse( void );
|
||||
void checkBTMouse( void );
|
||||
void mouseReceiveData(uint8_t src, PS2Mouse::MouseData mouseData);
|
||||
IRAM_ATTR static void hidControl( void * pvParameters );
|
||||
static void btPairingHandler(uint32_t pid, uint8_t trigger);
|
||||
inline uint32_t milliSeconds(void)
|
||||
{
|
||||
return( (uint32_t) (clock() ) );
|
||||
}
|
||||
|
||||
|
||||
enum HOST_CONFIG_MODES {
|
||||
HOST_CONFIG_OFF = 0x00,
|
||||
HOST_CONFIG_SCALING = 0x01,
|
||||
HOST_CONFIG_RESOLUTION = 0x02,
|
||||
};
|
||||
|
||||
// Structure to maintain configuration for the HID.
|
||||
//
|
||||
typedef struct {
|
||||
|
||||
struct {
|
||||
// Mouse data Adjustment and filtering options.
|
||||
//
|
||||
enum HID_MOUSE_RESOLUTION resolution;
|
||||
enum HID_MOUSE_SCALING scaling;
|
||||
enum HID_MOUSE_SAMPLING sampleRate;
|
||||
} mouse;
|
||||
|
||||
struct {
|
||||
// Host data for adjustment and configuration.
|
||||
enum HID_MOUSE_HOST_SCALING scaling;
|
||||
} host;
|
||||
|
||||
struct {
|
||||
// Configuration mode time period used to select configuration option. Once the middle key is held, the configuration option starts at 1, after this number of seconds
|
||||
// the configuration option advances to the next configuration item, and so on...
|
||||
uint16_t optionAdvanceDelay;
|
||||
} params;
|
||||
|
||||
} t_hidConfig;
|
||||
|
||||
// Structure to maintain an active settings for HID devices.
|
||||
typedef struct {
|
||||
enum HID_INPUT_DEVICE hidDevice; // Active HID device, only one can be active.
|
||||
enum HID_DEVICE_TYPES deviceType; // Type of device which is active.
|
||||
bool ps2Active; // Flag to indicate PS/2 device is online and active.
|
||||
uint32_t noEchoCount = 0L; // Echo back counter, used for testing if a keyboard is online.
|
||||
TickType_t ps2CheckTimer = 0; // Check timer, used for timing periodic keyboard checks.
|
||||
|
||||
// Mouse control variables.
|
||||
uint32_t noValidMouseMessage = 0;
|
||||
int wheelCnt = 0;
|
||||
uint32_t loopTimer = 0;
|
||||
bool middleKeyPressed = false;
|
||||
PS2Mouse::MouseData mouseData;
|
||||
|
||||
// Flag to indicate the mouse is active and online.
|
||||
bool active;
|
||||
|
||||
// Flag to indicate the configuration data has been updated.
|
||||
bool updated;
|
||||
|
||||
// Configuration mode selected when middle button pressed.
|
||||
enum HOST_CONFIG_MODES configMode;
|
||||
|
||||
// Mutex to block access during maintenance tasks.
|
||||
SemaphoreHandle_t mutexInternal;
|
||||
|
||||
// Callback for streaming input devices with data to be processed.
|
||||
std::function<void(t_mouseMessageElement)> dataCallback;
|
||||
} t_hidControl;
|
||||
|
||||
// Current configuration of the HID.
|
||||
t_hidConfig hidConfig;
|
||||
|
||||
// Variables to control the HID.
|
||||
t_hidControl hidCtrl;
|
||||
|
||||
// Handle to the persistent storage api.
|
||||
nvs_handle_t nvsHandle;
|
||||
|
||||
// Name of this class, used for NVS access.
|
||||
std::string className;
|
||||
|
||||
// NVS persistence object.
|
||||
NVS *nvs;
|
||||
|
||||
// LED activity object handle.
|
||||
LED *led;
|
||||
|
||||
// SWITCH object handle.
|
||||
SWITCH *sw;
|
||||
|
||||
// Keyboard object for PS/2 data retrieval and management.
|
||||
PS2KeyAdvanced *ps2Keyboard;
|
||||
|
||||
// Keyboard object for Bluetooth data retrieval and management.
|
||||
BTHID *btHID;
|
||||
|
||||
// Mouse object for PS/2 data retrieval and management.
|
||||
PS2Mouse *ps2Mouse;
|
||||
|
||||
// Thread handle for the HID control thread.
|
||||
TaskHandle_t TaskHID = NULL;
|
||||
};
|
||||
#endif // HID_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/KeyInterface.h
|
||||
203
main/include/KeyInterface.h
Normal file
203
main/include/KeyInterface.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: KeyInterface.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Virtual class definition on which all host interfaces, instantiated as a singleton,
|
||||
// are based.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef KEYINTERFACE_H
|
||||
#define KEYINTERFACE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Define a virtual class which acts as the base and specification of all super classes forming host
|
||||
// interface objects.
|
||||
class KeyInterface {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define KEYIF_VERSION 1.01
|
||||
|
||||
public:
|
||||
// Suspend flag. When active, the interface components enter an idle state after completing there latest cycle.
|
||||
bool suspend = false;
|
||||
bool suspended = true;
|
||||
|
||||
// NVS object.
|
||||
NVS *nvs;
|
||||
|
||||
// LED object.
|
||||
LED *led;
|
||||
|
||||
// HID object, used for keyboard input.
|
||||
HID *hid;
|
||||
|
||||
// Prototypes.
|
||||
KeyInterface(void) {};
|
||||
virtual ~KeyInterface(void) {};
|
||||
KeyInterface(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID) { init(getClassName(__PRETTY_FUNCTION__), hdlNVS, hdlLED, hdlHID, ifMode); };
|
||||
KeyInterface(NVS *hdlNVS, HID *hdlHID) { init(getClassName(__PRETTY_FUNCTION__), hdlNVS, hdlHID); };
|
||||
void reconfigADC2Ports(bool setAsOutput);
|
||||
void suspendInterface(bool suspendIf);
|
||||
virtual bool isSuspended(bool waitForSuspend);
|
||||
virtual bool isRunning(bool waitForRelease);
|
||||
virtual void identify(void) { };
|
||||
virtual void init(const char * subClassName, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, uint32_t ifMode);
|
||||
virtual void init(const char * subClassName, NVS *hdlNVS, HID *hdlHID);
|
||||
// Persistence.
|
||||
virtual bool persistConfig(void) { return(true); }
|
||||
|
||||
// Key mapping.
|
||||
virtual IRAM_ATTR uint32_t mapKey(uint16_t scanCode) { return(0); };
|
||||
virtual bool createKeyMapFile(std::fstream &outFile) { return(false); };
|
||||
virtual bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size) { return(false); };
|
||||
virtual bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray) { return(false); }
|
||||
virtual bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly) { return(false); };
|
||||
virtual std::string getKeyMapFileName(void) { return("nokeymap.bin"); };
|
||||
virtual void getKeyMapHeaders(std::vector<std::string>& headerList) { };
|
||||
virtual void getKeyMapTypes(std::vector<std::string>& typeList) { };
|
||||
virtual bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option) { return(true); }
|
||||
virtual bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start) { return(true); };
|
||||
// Mouse config.
|
||||
virtual void getMouseConfigTypes(std::vector<std::string>& typeList) { };
|
||||
virtual bool getMouseSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option) { return(true); }
|
||||
virtual bool setMouseConfigValue(std::string paramName, std::string paramValue) { return(true); }
|
||||
|
||||
// Method to suspend an active interface thread by holding in a tight loop, yielding to the OS. This method was chosen rather than the more conventional
|
||||
// vTaskSuspend as it allows multiple threads, without giving a handle, to yield if required for a fixed period or indefinitely until the suspend mode is de-activated.
|
||||
// The method is inline to avoid a call overhead as it is generally used in time sensitive interface timing.
|
||||
inline virtual void yield(uint32_t delay)
|
||||
{
|
||||
// If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
if(this->suspend)
|
||||
{
|
||||
this->suspended = true;
|
||||
while(this->suspend)
|
||||
{
|
||||
vTaskDelay(100);
|
||||
}
|
||||
this->suspended = false;
|
||||
} else
|
||||
// Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
{
|
||||
vTaskDelay(delay);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to see if the interface must enter suspend mode.
|
||||
//
|
||||
inline virtual bool suspendRequested(void)
|
||||
{
|
||||
return(this->suspend);
|
||||
}
|
||||
|
||||
// Helper method to identify the sub class, this is used in non volatile key management.
|
||||
// Warning: This method wont work if optimisation for size is enabled on the compiler.
|
||||
const char *getClassName(const std::string& prettyFunction)
|
||||
{
|
||||
// First find the CLASS :: METHOD seperation.
|
||||
size_t colons = prettyFunction.find("::");
|
||||
|
||||
// None, then this is not a class.
|
||||
if (colons == std::string::npos)
|
||||
return "::";
|
||||
|
||||
// Split out the class name.
|
||||
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
|
||||
size_t end = colons - begin;
|
||||
|
||||
// Return the name.
|
||||
return(prettyFunction.substr(begin,end).c_str());
|
||||
}
|
||||
|
||||
// Helper method to change a file extension.
|
||||
void replaceExt(std::string& fileName, const std::string& newExt)
|
||||
{
|
||||
// Locals.
|
||||
std::string::size_type extPos = fileName.rfind('.', fileName.length());
|
||||
|
||||
if(extPos != std::string::npos)
|
||||
{
|
||||
fileName.replace(extPos+1, newExt.length(), newExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
// Method to return the class version number.
|
||||
virtual float version(void)
|
||||
{
|
||||
return(KEYIF_VERSION);
|
||||
}
|
||||
|
||||
// Method to return the name of the inferface class.
|
||||
virtual std::string ifName(void)
|
||||
{
|
||||
return(subClassName);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
virtual IRAM_ATTR void selectOption(uint8_t optionCode) {};
|
||||
|
||||
// Name of the sub-class for this instantiation.
|
||||
std::string subClassName;
|
||||
|
||||
// Thread handle for the LED control thread.
|
||||
TaskHandle_t TaskLEDIF = NULL;
|
||||
};
|
||||
#endif // KEYINTERFACE_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/LED.h
|
||||
181
main/include/LED.h
Normal file
181
main/include/LED.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: LED.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Class definition for the control of a single LED. The LED is used to indicate to a
|
||||
// user a desired status. This class is normally instantiated as a singleton and
|
||||
// manipulated by public methods.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LED_H
|
||||
#define LED_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "PS2KeyAdvanced.h"
|
||||
#include "PS2Mouse.h"
|
||||
#include "NVS.h"
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Define a class to encapsulate a LED and required control mechanisms,
|
||||
class LED {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define LED_VERSION 1.01
|
||||
|
||||
public:
|
||||
// Interface LED activity modes.
|
||||
enum LED_MODE {
|
||||
LED_MODE_OFF = 0x00,
|
||||
LED_MODE_ON = 0x01,
|
||||
LED_MODE_BLINK_ONESHOT = 0x02,
|
||||
LED_MODE_BLINK = 0x03,
|
||||
};
|
||||
|
||||
// Interface LED duty cycle.
|
||||
enum LED_DUTY_CYCLE {
|
||||
LED_DUTY_CYCLE_OFF = 0x00,
|
||||
LED_DUTY_CYCLE_10 = 0x01,
|
||||
LED_DUTY_CYCLE_20 = 0x02,
|
||||
LED_DUTY_CYCLE_30 = 0x03,
|
||||
LED_DUTY_CYCLE_40 = 0x04,
|
||||
LED_DUTY_CYCLE_50 = 0x05,
|
||||
LED_DUTY_CYCLE_60 = 0x06,
|
||||
LED_DUTY_CYCLE_70 = 0x07,
|
||||
LED_DUTY_CYCLE_80 = 0x08,
|
||||
LED_DUTY_CYCLE_90 = 0x09,
|
||||
};
|
||||
|
||||
// Prototypes.
|
||||
LED(uint32_t hwPin);
|
||||
LED(void);
|
||||
virtual ~LED(void) {};
|
||||
void identify(void) { };
|
||||
|
||||
// LED Control.
|
||||
bool setLEDMode(enum LED_MODE mode, enum LED_DUTY_CYCLE dutyCycle, uint32_t maxBlinks, uint64_t usDutyPeriod, uint64_t msInterPeriod);
|
||||
IRAM_ATTR static void ledInterface(void *pvParameters);
|
||||
void ledInit(uint8_t ledPin);
|
||||
|
||||
// Helper method to identify the sub class, this is used in non volatile key management.
|
||||
// Warning: This method wont work if optimisation for size is enabled on the compiler.
|
||||
const char *getClassName(const std::string& prettyFunction)
|
||||
{
|
||||
// First find the CLASS :: METHOD seperation.
|
||||
size_t colons = prettyFunction.find("::");
|
||||
|
||||
// None, then this is not a class.
|
||||
if (colons == std::string::npos)
|
||||
return "::";
|
||||
|
||||
// Split out the class name.
|
||||
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
|
||||
size_t end = colons - begin;
|
||||
|
||||
// Return the name.
|
||||
return(prettyFunction.substr(begin,end).c_str());
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
// Method to return the class version number.
|
||||
virtual float version(void)
|
||||
{
|
||||
return(LED_VERSION);
|
||||
}
|
||||
|
||||
// Method to return the name of the inferface class.
|
||||
virtual std::string ifName(void)
|
||||
{
|
||||
return(className);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
|
||||
// Structure to maintain configuration for the LED.
|
||||
//
|
||||
typedef struct {
|
||||
bool valid; // The configuration is valid and should be processed.
|
||||
bool updated; // This configuration is an update to override current configuration.
|
||||
|
||||
enum LED_MODE mode; // Mode of LED activity.
|
||||
enum LED_DUTY_CYCLE dutyCycle; // Duty cycle of the BLINK LED period.
|
||||
uint32_t maxBlinks; // Maximum number of blinks before switching to LED off mode.
|
||||
uint64_t dutyPeriod; // Period, is micro-seconds of the full duty cycle.
|
||||
uint64_t interPeriod; // Period, is milli-seconds between LED activity.
|
||||
} t_ledConfig;
|
||||
|
||||
// Structure to maintain an active setting for the LED. The LED control thread uses these values to effect the required lighting of the LED.
|
||||
typedef struct {
|
||||
// Current, ie. working LED config acted upon by the LED thread.
|
||||
t_ledConfig currentConfig;
|
||||
// New config to replace current on next state.
|
||||
t_ledConfig newConfig;
|
||||
|
||||
// Led GPIO pin.
|
||||
uint8_t ledPin;
|
||||
|
||||
// Runtime parameters for state machine and control.
|
||||
uint32_t blinkCnt; // count of blink on periods.
|
||||
|
||||
// Mutex to block access to limit one thread at a time.
|
||||
SemaphoreHandle_t mutexInternal;
|
||||
} t_ledControl;
|
||||
|
||||
// Variables to control the LED.
|
||||
t_ledControl ledCtrl;
|
||||
|
||||
// Name of the class for this instantiation.
|
||||
std::string className;
|
||||
|
||||
// Thread handle for the LED control thread.
|
||||
TaskHandle_t TaskLEDIF = NULL;
|
||||
};
|
||||
#endif // LED_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/MZ2528.h
|
||||
534
main/include/MZ2528.h
Normal file
534
main/include/MZ2528.h
Normal file
@@ -0,0 +1,534 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: MZ2528.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the MZ-2500/MZ-2800 PS/2 logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to reflect bluetooth.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MZ2528_H
|
||||
#define MZ2528_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the MZ-2500/MZ-2800 interface.
|
||||
class MZ2528 : public KeyInterface {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define MZ2528IF_VERSION 1.02
|
||||
#define MZ2528IF_KEYMAP_FILE "MZ2528_KeyMap.BIN"
|
||||
#define PS2TBL_MZ_MAXROWS 165
|
||||
#define PS2TBL_MZ_MAX_MKROW 3
|
||||
#define PS2TBL_MZ_MAX_BRKROW 2
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2CTRL_NONE 0x00 // No keys active = 0
|
||||
#define PS2CTRL_SHIFT 0x01 // Shfit Key active = 1
|
||||
#define PS2CTRL_CTRL 0x02 // Ctrl Key active = 1
|
||||
#define PS2CTRL_CAPS 0x04 // CAPS active = 1
|
||||
#define PS2CTRL_ALT 0x08 // ALT active = 1
|
||||
#define PS2CTRL_ALTGR 0x10 // ALTGR active = 1
|
||||
#define PS2CTRL_GUI 0x20 // GUI Key active = 1
|
||||
#define PS2CTRL_FUNC 0x40 // Special Function Keys active = 1
|
||||
#define PS2CTRL_BREAK 0x80 // BREAK Key active = 1
|
||||
#define PS2CTRL_EXACT 0x80 // EXACT Match active = 1
|
||||
|
||||
// The MZ-2500 machine can emulate 3 models, the MZ-80B, MZ-2000 and the MZ-2500. The MZ-2800 provides a new mode as well as the MZ-2500 mode and each has slight
|
||||
// keyboard differences. This requires tagging of machine specific mappings. Normally a mapping would be MZ_ALL, ie. applied to all models, but if a machine specific
|
||||
// mapping appears and it matches the current machine mode, this mapping is chosen.
|
||||
#define MZ_ALL 0xFF
|
||||
#define MZ_80B 0x01
|
||||
#define MZ_2000 0x02
|
||||
#define MZ_2500 0x04
|
||||
#define MZ_2800 0x08
|
||||
|
||||
// Keyboard mapping table select list for target machine.
|
||||
#define MZ2528_SEL_ALL "ALL"
|
||||
#define MZ2528_SEL_MZ_80B "MZ80B"
|
||||
#define MZ2528_SEL_MZ_2000 "MZ2000"
|
||||
#define MZ2528_SEL_MZ_2500 "MZ2500"
|
||||
#define MZ2528_SEL_MZ_2800 "MZ2800"
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to MZ Scan Matrix.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> MZ Scan Matrix
|
||||
|
||||
|
||||
// Keyboard mapping table column names.
|
||||
#define PS2TBL_PS2KEYCODE_NAME "PS/2 KeyCode"
|
||||
#define PS2TBL_PS2CTRL_NAME "PS/2 Control Key"
|
||||
#define PS2TBL_KEYBOARDMODEL_NAME "For Keyboard"
|
||||
#define PS2TBL_MACHINE_NAME "For Host Model"
|
||||
#define PS2TBL_MZ_MK_ROW1_NAME "Make Row 1"
|
||||
#define PS2TBL_MZ_MK_KEY1_NAME "Key 1"
|
||||
#define PS2TBL_MZ_MK_ROW2_NAME "Row 2"
|
||||
#define PS2TBL_MZ_MK_KEY2_NAME "Key 2"
|
||||
#define PS2TBL_MZ_MK_ROW3_NAME "Row 3"
|
||||
#define PS2TBL_MZ_MK_KEY3_NAME "Key 3"
|
||||
#define PS2TBL_MZ_BRK_ROW1_NAME "Break Row 1"
|
||||
#define PS2TBL_MZ_BRK_KEY1_NAME "Key 1"
|
||||
#define PS2TBL_MZ_BRK_ROW2_NAME "Row 2"
|
||||
#define PS2TBL_MZ_BRK_KEY2_NAME "Key 2"
|
||||
|
||||
// Keyboard mapping table column types.
|
||||
#define PS2TBL_PS2KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PS2CTRL_TYPE "custom_cbp_ps2ctrl"
|
||||
#define PS2TBL_KEYBOARDMODEL_TYPE "custom_cbp_keybmodel"
|
||||
#define PS2TBL_MACHINE_TYPE "custom_cbp_machine"
|
||||
#define PS2TBL_MZ_MK_ROW1_TYPE "custom_rdp_mzrow"
|
||||
#define PS2TBL_MZ_MK_KEY1_TYPE "hex"
|
||||
#define PS2TBL_MZ_MK_ROW2_TYPE "custom_rdp_mzrow"
|
||||
#define PS2TBL_MZ_MK_KEY2_TYPE "hex"
|
||||
#define PS2TBL_MZ_MK_ROW3_TYPE "custom_rdp_mzrow"
|
||||
#define PS2TBL_MZ_MK_KEY3_TYPE "hex"
|
||||
#define PS2TBL_MZ_BRK_ROW1_TYPE "custom_rdp_mzrow"
|
||||
#define PS2TBL_MZ_BRK_KEY1_TYPE "hex"
|
||||
#define PS2TBL_MZ_BRK_ROW2_TYPE "custom_rdp_mzrow"
|
||||
#define PS2TBL_MZ_BRK_KEY2_TYPE "hex"
|
||||
|
||||
// Keyboard mapping table select list for PS2CTRL.
|
||||
#define PS2TBL_PS2CTRL_SEL_NONE "NONE"
|
||||
#define PS2TBL_PS2CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PS2TBL_PS2CTRL_SEL_CTRL "CTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_CAPS "CAPS"
|
||||
#define PS2TBL_PS2CTRL_SEL_ALT "ALT"
|
||||
#define PS2TBL_PS2CTRL_SEL_ALTGR "ALTGR"
|
||||
#define PS2TBL_PS2CTRL_SEL_GUI "GUI"
|
||||
#define PS2TBL_PS2CTRL_SEL_FUNC "FUNC"
|
||||
#define PS2TBL_PS2CTRL_SEL_EXACT "EXACT"
|
||||
|
||||
// Keyboard mapping table select list for Model of keyboard.
|
||||
#define KEYMAP_SEL_STANDARD "ALL"
|
||||
#define KEYMAP_SEL_UK_WYSE_KB3926 "UK_WYSE_KB3926"
|
||||
#define KEYMAP_SEL_JAPAN_OADG109 "JAPAN_OADG109"
|
||||
#define KEYMAP_SEL_JAPAN_SANWA_SKBL1 "JAPAN_SANWA_SKBL1"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_4 "KEYBOARD_4"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_5 "KEYBOARD_5"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_6 "KEYBOARD_6"
|
||||
#define KEYMAP_SEL_UK_PERIBOARD_810 "UK_PERIBOARD_810"
|
||||
#define KEYMAP_SEL_UK_OMOTON_K8508 "UK_OMOTON_K8508"
|
||||
|
||||
// Keyboard models. The base on which this interface was created was a Wyse KB3926 PS/2 Keyboard and this is deemed STANDARD. Other models need to insert difference maps
|
||||
// prior to the STANDARD entry along with the keyboard model so that it is processed first thus allowing differing keyboards with different maps.
|
||||
#define KEYMAP_STANDARD 0xFF
|
||||
#define KEYMAP_UK_WYSE_KB3926 0x01
|
||||
#define KEYMAP_JAPAN_OADG109 0x02
|
||||
#define KEYMAP_JAPAN_SANWA_SKBL1 0x04
|
||||
#define KEYMAP_NOT_ASSIGNED_4 0x08
|
||||
#define KEYMAP_NOT_ASSIGNED_5 0x10
|
||||
#define KEYMAP_NOT_ASSIGNED_6 0x20
|
||||
#define KEYMAP_UK_PERIBOARD_810 0x40
|
||||
#define KEYMAP_UK_OMOTON_K8508 0x80
|
||||
|
||||
public:
|
||||
// Prototypes.
|
||||
MZ2528(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, const char *fsPath);
|
||||
MZ2528(NVS *hdlNVS, HID *hdlHID, const char *fsPath);
|
||||
MZ2528(void);
|
||||
~MZ2528(void);
|
||||
bool createKeyMapFile(std::fstream &outFile);
|
||||
bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size);
|
||||
bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray);
|
||||
bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly);
|
||||
std::string getKeyMapFileName(void) { return(MZ2528IF_KEYMAP_FILE); };
|
||||
void getKeyMapHeaders(std::vector<std::string>& headerList);
|
||||
void getKeyMapTypes(std::vector<std::string>& typeList);
|
||||
bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start);
|
||||
|
||||
// Overloaded method to see if the interface must enter suspend mode, either triggered by an external event or internal.
|
||||
//
|
||||
inline bool suspendRequested(void)
|
||||
{
|
||||
return(this->suspend);
|
||||
}
|
||||
|
||||
// // Method to overload the suspend mechanism and include the core release mechanism. Core release is needed in order to use ESP32 API's such as NVS.
|
||||
// // The method is inline to avoid a call overhead as it is generally used in time sensitive interface timing.
|
||||
// inline void yield(uint32_t delay)
|
||||
// {
|
||||
// // If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
// if(this->suspend)
|
||||
// {
|
||||
// this->suspended = true;
|
||||
// while(this->suspend)
|
||||
// {
|
||||
// vTaskDelay(100);
|
||||
// }
|
||||
// this->suspended = false;
|
||||
// } else
|
||||
// // Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
// {
|
||||
// vTaskDelay(delay);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(MZ2528IF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
void updateMirrorMatrix(void);
|
||||
uint32_t mapKey(uint16_t scanCode);
|
||||
IRAM_ATTR static void mz25Interface(void *pvParameters );
|
||||
IRAM_ATTR static void mz28Interface(void *pvParameters );
|
||||
IRAM_ATTR static void hidInterface(void *pvParameters );
|
||||
void selectOption(uint8_t optionCode);
|
||||
bool loadKeyMap();
|
||||
bool saveKeyMap(void);
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// Overload the base yield method to include suspension of the PS/2 Keyboard interface. This interface uses interrupts which are not mutex protected and clash with the
|
||||
// WiFi API methods.
|
||||
// inline void yield(uint32_t delay)
|
||||
// {
|
||||
// // If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
// if(this->suspend)
|
||||
// {
|
||||
// // Suspend the keyboard interface.
|
||||
// Keyboard->suspend(true);
|
||||
//
|
||||
// // Use the base method logic.
|
||||
// KeyInterface::yield(delay);
|
||||
//
|
||||
// // Release the keyboard interface.
|
||||
// Keyboard->suspend(false);
|
||||
// } else
|
||||
// // Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
// {
|
||||
// KeyInterface::yield(delay);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Structure to encapsulate a single key map from PS/2 to MZ-2500/MZ-2800.
|
||||
typedef struct {
|
||||
uint8_t ps2KeyCode;
|
||||
uint8_t ps2Ctrl;
|
||||
uint8_t keyboardModel;
|
||||
uint8_t machine;
|
||||
uint8_t mkRow[PS2TBL_MZ_MAX_MKROW];
|
||||
uint8_t mkKey[PS2TBL_MZ_MAX_MKROW];
|
||||
uint8_t brkRow[PS2TBL_MZ_MAX_BRKROW];
|
||||
uint8_t brkKey[PS2TBL_MZ_MAX_BRKROW];
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[PS2TBL_MZ_MAXROWS];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to maintain the MZ2528 interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t activeKeyboardMap; // Model of keyboard a keymap entry is applicable to.
|
||||
uint8_t activeMachineModel; // Machine model a keymap entry is applicable to.
|
||||
} params;
|
||||
} t_mzConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_mzConfig mzConfig;
|
||||
|
||||
// Structure to manage the translated key matrix. This is updated by the ps2Interface thread and read by the mzInterface thead.
|
||||
typedef struct {
|
||||
uint8_t strobeAll; // Strobe All flag, 16 possible rows have the same column AND'd together to create this 8bit map. It is used to see if any key has been pressed.
|
||||
uint32_t strobeAllAsGPIO; // Strobe All signal but as a GPIO bit map to save time in the interface thread.
|
||||
uint8_t keyMatrix[16]; // Key matrix as a 16x8 matrix.
|
||||
uint32_t keyMatrixAsGPIO[16]; // Key matrix mapped as GPIO bits to save time in the interface thread.
|
||||
bool mode2500;
|
||||
bool optionSelect; // Flag to indicate a user requested keyboard configuration option is being selected.
|
||||
std::string fsPath; // Path on the underlying filesystem where storage is mounted and accessible.
|
||||
t_keyMapEntry *kme; // Pointer to an array in memory to contain PS2 to MZ-2500/MZ-2800 mapping values.
|
||||
int kmeRows; // Number of rows in the kme table.
|
||||
std::string keyMapFileName; // Name of file where extension or replacement key map entries are stored.
|
||||
bool noKeyPressed; // Flag to indicate no key has been pressed.
|
||||
bool persistConfig; // Flag to request saving of the config into NVS storage.
|
||||
} t_mzControl;
|
||||
|
||||
// Thread handles - one per function, ie. HID interface and host target interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Control structure to control interaction and mapping of keys for the host.
|
||||
t_mzControl mzControl;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE mzMutex;
|
||||
|
||||
// Flag to indicate host interface should yield the CPU.
|
||||
volatile bool yieldHostInterface;
|
||||
|
||||
// // Keyboard object for PS/2 data retrieval and management.
|
||||
// PS2KeyAdvanced *Keyboard;
|
||||
|
||||
// HID object, used for keyboard input.
|
||||
// HID *hid;
|
||||
|
||||
// Lookup table to matrix row/column co-ordinates.
|
||||
//
|
||||
// Given that the MZ-2500 can emulate 3 machines and each machine has it's own mapping, differences are tagged by machine name, ie. ALL, MZ80B, MZ2000, MZ2500
|
||||
//
|
||||
// If a PS2 key is matched, then the Matrix is updated using MK_ROW to point into the array with MK_KEY being the column value, equivalent of strobe line and
|
||||
// the required KEY bits to be set. Upto 3 matrix bits can be set (3 key presses on the MZ-2500 keyboard) per PS/2 key. Upto 2 matrix releases can be set per
|
||||
// PS/2 key. A key release is used when a modifier may already have been pressed, ie. SHIFT and it needs to be released to set the required key into the matrix.
|
||||
// A set bit = 1, reset bits = 0 but is inverted in the actual matrix (1 = inactive, 0 = active), this applies for releases two, if bit = 1 then that key will be released.
|
||||
// The table is scanned for a match from top to bottom. The first match is used so order is important. Japanese characters are being added as I gleam more information.
|
||||
|
||||
///////////////////////////
|
||||
// MZ-2500 Keyboard Map. //
|
||||
///////////////////////////
|
||||
//
|
||||
// Row D7 D6 D5 D4 D3 D2 D1 D0
|
||||
//----------------------------------------------------------------------------------
|
||||
// 0 F8 F7 F6 F5 F4 F3 F2 F1
|
||||
// 1 KP - KP + KP . KP , KP 9 KP 8 F1O F9
|
||||
// 2 KP 7 KP 6 KP 5 KP 4 KP 3 KP 2 KP 1 KP 0
|
||||
// 3 BREAK RIGHT LEFT DOWN UP RETURN SPACE TAB
|
||||
// 4 G F E D C B A / ?
|
||||
// 5 O N M L K J I H
|
||||
// 6 W V U T S R Q P
|
||||
// 7 , < . > _ YEN | ^ '¿ Z ¿ Y X ¿
|
||||
// 8 7 ' 6 & 5 % 4 $ 3 # 2 " 1 ! 0
|
||||
// 9 [ { @ ` - = ; + : * 9 ) 8 (
|
||||
// 10 KP / KP * ESC BACKSPACE INST/DEL CLR/HOME COPY ] }
|
||||
// 11 CTRL KANA SHIFT LOCK GRAPH
|
||||
// 12 KJ2 KJ1
|
||||
// 13 HELP ARGO
|
||||
//
|
||||
// Col 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
// --------------------------------------------------------------------------------------------------------------------------------------
|
||||
// D0 F1 F9 KP 0 TAB / ? H P X 0 8 ( ] } GRAPH KJ1 ARGO
|
||||
// D1 F2 F10 KP 1 SPACE A I Q Y 1 ! 9 ) COPY LOCK KJ2 HELP
|
||||
// D2 F3 KP 8 KP 2 RETURN B J R Z 2 " : * CLR/HOME SHIFT
|
||||
// D3 F4 KP 9 KP 3 UP C K S ^ '¿ 3 # ; + INST/DEL KANA
|
||||
// D4 F5 KP , KP 4 DOWN D L T YEN | 4 $ - = BACKSPACE CTRL
|
||||
// D5 F6 KP . KP 5 LEFT E M U _ 5 % @ ` ESC
|
||||
// D6 F7 KP + KP 6 RIGHT F N V . > 6 & [ { KP *
|
||||
// D7 F8 KP - KP 7 BREAK G O W , < 7 ' KP /
|
||||
//
|
||||
// This initial mapping is for the UK Wyse KB-3926 PS/2 keyboard and his equates to KEYMAP_STANDARD.
|
||||
//
|
||||
t_keyMap PS2toMZ = {
|
||||
{
|
||||
// < Keys to be applied on match > < Keys to be reset on match >
|
||||
// PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MK_ROW1 MK_ROW2 MK_ROW3 MK_KEY1 MK_KEY2 MK_KEY3 BRK_ROW1 BRK_ROW2 BRK_KEY1 BRK_KEY2
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F1
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F2
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F3
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F4
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F5
|
||||
{ PS2_KEY_F6, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F6
|
||||
{ PS2_KEY_F7, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F7
|
||||
{ PS2_KEY_F8, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x00, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F8
|
||||
{ PS2_KEY_F9, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F9
|
||||
{ PS2_KEY_F10, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F10
|
||||
{ PS2_KEY_F11, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0D, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // HELP
|
||||
{ PS2_KEY_F12, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // COPY
|
||||
{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // TAB
|
||||
{ PS2_KEY_0, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x02, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Close Right Bracket )
|
||||
{ PS2_KEY_0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 0
|
||||
{ PS2_KEY_1, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x02, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Exclamation
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 1
|
||||
{ PS2_KEY_2, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Double quote.
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 2
|
||||
{ PS2_KEY_3, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Pound Sign -> Hash
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 3
|
||||
{ PS2_KEY_4, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Dollar
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 4
|
||||
{ PS2_KEY_5, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x20, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Percent
|
||||
{ PS2_KEY_5, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 5
|
||||
{ PS2_KEY_6, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // Kappa
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 6
|
||||
{ PS2_KEY_7, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Ampersand
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 7
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Star
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 8
|
||||
{ PS2_KEY_9, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Open Left Bracket (
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // 9
|
||||
{ PS2_KEY_A, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // a
|
||||
{ PS2_KEY_A, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // A
|
||||
{ PS2_KEY_B, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // b
|
||||
{ PS2_KEY_B, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // B
|
||||
{ PS2_KEY_C, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // c
|
||||
{ PS2_KEY_C, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // C
|
||||
{ PS2_KEY_D, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // d
|
||||
{ PS2_KEY_D, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // D
|
||||
{ PS2_KEY_E, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // e
|
||||
{ PS2_KEY_E, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // E
|
||||
{ PS2_KEY_F, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // f
|
||||
{ PS2_KEY_F, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // F
|
||||
{ PS2_KEY_G, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // g
|
||||
{ PS2_KEY_G, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // G
|
||||
{ PS2_KEY_H, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // h
|
||||
{ PS2_KEY_H, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // H
|
||||
{ PS2_KEY_I, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // i
|
||||
{ PS2_KEY_I, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // I
|
||||
{ PS2_KEY_J, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // j
|
||||
{ PS2_KEY_J, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // J
|
||||
{ PS2_KEY_K, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // k
|
||||
{ PS2_KEY_K, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // K
|
||||
{ PS2_KEY_L, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // l
|
||||
{ PS2_KEY_L, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // L
|
||||
{ PS2_KEY_M, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // m
|
||||
{ PS2_KEY_M, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // M
|
||||
{ PS2_KEY_N, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // n
|
||||
{ PS2_KEY_N, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // N
|
||||
{ PS2_KEY_O, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // o
|
||||
{ PS2_KEY_O, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x05, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // O
|
||||
{ PS2_KEY_P, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // p
|
||||
{ PS2_KEY_P, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // P
|
||||
{ PS2_KEY_Q, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // q
|
||||
{ PS2_KEY_Q, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Q
|
||||
{ PS2_KEY_R, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // r
|
||||
{ PS2_KEY_R, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // R
|
||||
{ PS2_KEY_S, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // s
|
||||
{ PS2_KEY_S, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // S
|
||||
{ PS2_KEY_T, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // t
|
||||
{ PS2_KEY_T, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // T
|
||||
{ PS2_KEY_U, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // u
|
||||
{ PS2_KEY_U, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // U
|
||||
{ PS2_KEY_V, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // v
|
||||
{ PS2_KEY_V, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // V
|
||||
{ PS2_KEY_W, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // w
|
||||
{ PS2_KEY_W, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x06, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // W
|
||||
{ PS2_KEY_X, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // x
|
||||
{ PS2_KEY_X, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // X
|
||||
{ PS2_KEY_Y, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // y
|
||||
{ PS2_KEY_Y, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Y
|
||||
{ PS2_KEY_Z, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // z
|
||||
{ PS2_KEY_Z, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Z
|
||||
// PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MK_ROW1 MK_ROW2 MK_ROW3 MK_KEY1 MK_KEY2 MK_KEY3 BRK_ROW1 BRK_ROW2 BRK_KEY1 BRK_KEY2
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Space
|
||||
{ PS2_KEY_COMMA, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0x0B, 0xFF, 0x80, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Less Than <
|
||||
{ PS2_KEY_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Comma ,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // Colon :
|
||||
{ PS2_KEY_SEMI, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Semi-Colon ;
|
||||
{ PS2_KEY_DOT, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0x0B, 0xFF, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Greater Than >
|
||||
{ PS2_KEY_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Full stop .
|
||||
{ PS2_KEY_DIV, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_2000, 0x07, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // Question ?
|
||||
{ PS2_KEY_DIV, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_80B, 0x07, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // Question ?
|
||||
{ PS2_KEY_DIV, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x04, 0x0B, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Question ?
|
||||
{ PS2_KEY_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x04, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Divide /
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_2000, 0x08, 0x0B, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Upper bar
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_80B, 0x08, 0x0B, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Upper bar
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // Underscore
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, //
|
||||
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_80B, 0x09, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // At @
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0x0B, 0xFF, 0x04, 0xFF, }, // At @
|
||||
{ PS2_KEY_APOS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x80, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Single quote '
|
||||
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Open Left Brace {
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Open Left Square Bracket [
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Plus +
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Equal =
|
||||
{ PS2_KEY_CAPS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // LOCK
|
||||
{ PS2_KEY_ENTER, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // ENTER/RETURN
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0x0B, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Close Right Brace }
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Close Right Square Bracket ]
|
||||
{ PS2_KEY_BACK, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0x0B, 0xFF, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, //
|
||||
{ PS2_KEY_BACK, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x07, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_BTICK, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0x07, 0x0B, 0xFF, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Pipe
|
||||
{ PS2_KEY_BTICK, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x09, 0x0B, 0xFF, 0x20, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Back tick `
|
||||
{ PS2_KEY_HASH, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_2000, 0x07, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Tilde
|
||||
{ PS2_KEY_HASH, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_80B, 0x07, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Tilde
|
||||
{ PS2_KEY_HASH, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Tilde has no mapping.
|
||||
{ PS2_KEY_HASH, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x08, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Hash
|
||||
{ PS2_KEY_BS, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Backspace
|
||||
{ PS2_KEY_ESC, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // ESCape
|
||||
{ PS2_KEY_SCROLL, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not assigned.
|
||||
{ PS2_KEY_INSERT, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0x0B, 0xFF, 0x08, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // INSERT
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC | PS2CTRL_SHIFT | PS2CTRL_EXACT, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0x0B, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // CLR
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // HOME
|
||||
{ PS2_KEY_PGUP, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not assigned.
|
||||
{ PS2_KEY_DELETE, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // DELETE
|
||||
{ PS2_KEY_END, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not assigned.
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_80B|MZ_2000|MZ_2500, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not mapped
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_2800, 0x0C, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Japanese Key - Previous
|
||||
{ PS2_KEY_UP_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Up Arrow
|
||||
{ PS2_KEY_L_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Left Arrow
|
||||
{ PS2_KEY_DN_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Down Arrow
|
||||
{ PS2_KEY_R_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Right Arrow
|
||||
{ PS2_KEY_NUM, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not assigned.
|
||||
|
||||
// Keypad.
|
||||
{ PS2_KEY_KP0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x02, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad 9
|
||||
{ PS2_KEY_KP_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Comma ,
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x01, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x0A, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Divide /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Keypad Ebter /
|
||||
|
||||
// PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MK_ROW1 MK_ROW2 MK_ROW3 MK_KEY1 MK_KEY2 MK_KEY3 BRK_ROW1 BRK_ROW2 BRK_KEY1 BRK_KEY2
|
||||
// Special keys.
|
||||
{ PS2_KEY_PRTSCR, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0D, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // ARGO KEY
|
||||
{ PS2_KEY_PAUSE, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // BREAK KEY
|
||||
{ PS2_KEY_L_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // GRAPH KEY
|
||||
{ PS2_KEY_L_ALT, PS2CTRL_FUNC | PS2CTRL_ALT, KEYMAP_STANDARD, MZ_ALL, 0x0C, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // KJ1 Sentence
|
||||
{ PS2_KEY_R_ALT, PS2CTRL_FUNC | PS2CTRL_ALTGR, KEYMAP_STANDARD, MZ_ALL, 0x0C, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // KJ2 Transform
|
||||
{ PS2_KEY_R_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // KANA KEY
|
||||
{ PS2_KEY_MENU, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Not assigned.
|
||||
// Modifiers are last, only being selected if an earlier match isnt made.
|
||||
{ PS2_KEY_L_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
|
||||
{ PS2_KEY_R_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
|
||||
{ PS2_KEY_L_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_ALL, 0x0B, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_80B|MZ_2000|MZ_2500, 0x0B, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Map to Control
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ_2800, 0x0C, 0xFF, 0xFF, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, // Japanese Key - Cancel
|
||||
{ 0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ_ALL, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // MZ2528_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/MZ5665.h
|
||||
574
main/include/MZ5665.h
Normal file
574
main/include/MZ5665.h
Normal file
@@ -0,0 +1,574 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: MZ5665.h
|
||||
// Created: Apr 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the Sharp MZ-6500 to HID (PS/2, Bluetooth) interface logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Apr 2022 - Initial write.
|
||||
// v1.01 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MZ5665_H
|
||||
#define MZ5665_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the Sharp MZ-6500 interface.
|
||||
class MZ5665 : public KeyInterface {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define MZ5665IF_VERSION 1.01
|
||||
#define MZ5665IF_KEYMAP_FILE "MZ5665_KeyMap.BIN"
|
||||
#define MAX_MZ5665_XMIT_KEY_BUF 16
|
||||
#define PS2TBL_MZ5665_MAXROWS 349
|
||||
|
||||
// MZ-6500 Key control bit mask.
|
||||
#define MZ5665_CTRL_GRAPH ((unsigned char) (1 << 4))
|
||||
#define MZ5665_CTRL_CAPS ((unsigned char) (1 << 3))
|
||||
#define MZ5665_CTRL_KANA ((unsigned char) (1 << 2))
|
||||
#define MZ5665_CTRL_SHIFT ((unsigned char) (1 << 1))
|
||||
#define MZ5665_CTRL_CTRL ((unsigned char) (1 << 0))
|
||||
|
||||
// Special key definition.
|
||||
#define MZ5665_KEY_UP 0x1E // ↑
|
||||
#define MZ5665_KEY_DOWN 0x1F // ↓
|
||||
#define MZ5665_KEY_LEFT 0x1D // ←
|
||||
#define MZ5665_KEY_RIGHT 0x1C // → →
|
||||
#define MZ5665_KEY_INS 0x12 // INS
|
||||
#define MZ5665_KEY_DEL 0x08 // DEL
|
||||
#define MZ5665_KEY_CLR 0x0C // CLR
|
||||
#define MZ5665_KEY_HOME 0x0B // HOME
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2CTRL_NONE 0x00 // No keys active = 0
|
||||
#define PS2CTRL_SHIFT 0x01 // Shfit Key active = 1
|
||||
#define PS2CTRL_CTRL 0x02 // Ctrl Key active = 1
|
||||
#define PS2CTRL_CAPS 0x04 // CAPS active = 1
|
||||
#define PS2CTRL_KANA 0x08 // KANA active = 1
|
||||
#define PS2CTRL_GRAPH 0x10 // GRAPH active = 1
|
||||
#define PS2CTRL_GUI 0x20 // GUI Key active = 1
|
||||
#define PS2CTRL_FUNC 0x40 // Special Function Keys active = 1
|
||||
#define PS2CTRL_BREAK 0x80 // BREAK Key active = 1
|
||||
#define PS2CTRL_EXACT 0x80 // EXACT Match active = 1
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to extract the MZ-6500 key code and control data.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> MZ-6500 Key Code + Ctrl Data
|
||||
|
||||
// Keyboard mapping table column names.
|
||||
#define PS2TBL_PS2KEYCODE_NAME "PS/2 KeyCode"
|
||||
#define PS2TBL_PS2CTRL_NAME "PS/2 Control Key"
|
||||
#define PS2TBL_KEYBOARDMODEL_NAME "For Keyboard"
|
||||
#define PS2TBL_MACHINE_NAME "For Host Model"
|
||||
#define PS2TBL_MZ5665_KEYCODE_NAME "MZ5665 KeyCode"
|
||||
#define PS2TBL_MZ5665__CTRL_NAME "MZ5665 Control Key"
|
||||
|
||||
// Keyboard mapping table column types.
|
||||
#define PS2TBL_PS2KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PS2CTRL_TYPE "custom_cbp_ps2ctrl"
|
||||
#define PS2TBL_KEYBOARDMODEL_TYPE "custom_cbp_keybmodel"
|
||||
#define PS2TBL_MACHINE_TYPE "custom_cbp_machine"
|
||||
#define PS2TBL_MZ5665_KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_MZ5665_CTRL_TYPE "custom_cbn_x1ctrl"
|
||||
|
||||
// Keyboard mapping table select list for PS2CTRL.
|
||||
#define PS2TBL_PS2CTRL_SEL_NONE "NONE"
|
||||
#define PS2TBL_PS2CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PS2TBL_PS2CTRL_SEL_CTRL "CTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_CAPS "CAPS"
|
||||
#define PS2TBL_PS2CTRL_SEL_KANA "KANA"
|
||||
#define PS2TBL_PS2CTRL_SEL_GRAPH "GRAPH"
|
||||
#define PS2TBL_PS2CTRL_SEL_GUI "GUI"
|
||||
#define PS2TBL_PS2CTRL_SEL_FUNC "FUNC"
|
||||
#define PS2TBL_PS2CTRL_SEL_EXACT "EXACT"
|
||||
|
||||
// Keyboard mapping table select list for Model of keyboard.
|
||||
#define KEYMAP_SEL_STANDARD "ALL"
|
||||
#define KEYMAP_SEL_UK_WYSE_KB3926 "UK_WYSE_KB3926"
|
||||
#define KEYMAP_SEL_JAPAN_OADG109 "JAPAN_OADG109"
|
||||
#define KEYMAP_SEL_JAPAN_SANWA_SKBL1 "JAPAN_SANWA_SKBL1"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_4 "KEYBOARD_4"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_5 "KEYBOARD_5"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_6 "KEYBOARD_6"
|
||||
#define KEYMAP_SEL_UK_PERIBOARD_810 "UK_PERIBOARD_810"
|
||||
#define KEYMAP_SEL_UK_OMOTON_K8508 "UK_OMOTON_K8508"
|
||||
|
||||
// Keyboard mapping table select list for target machine.
|
||||
#define MZ5665_SEL_ALL "ALL"
|
||||
|
||||
// Keyboard mapping table select list for MZ5665 Control codes.
|
||||
#define MZ5665_CTRL_SEL_GRAPH "GRAPH"
|
||||
#define MZ5665_CTRL_SEL_CAPS "CAPS"
|
||||
#define MZ5665_CTRL_SEL_KANA "KANA"
|
||||
#define MZ5665_CTRL_SEL_SHIFT "SHIFT"
|
||||
#define MZ5665_CTRL_SEL_CTRL "CTRL"
|
||||
|
||||
// The Sharp MZ-6500 Series was released over a number of years and each iteration added changes/updates. In order to cater for differences, it is possible to assign a key mapping
|
||||
// to a specific machine type(s) or all of the series by adding the flags below into the mapping table.
|
||||
#define MZ5665_ALL 0xFF
|
||||
|
||||
// Keyboard models. The base on which this interface was created was a Wyse KB3926 PS/2 Keyboard and this is deemed STANDARD. Other models need to insert difference maps
|
||||
// prior to the STANDARD entry along with the keyboard model so that it is processed first thus allowing differing keyboards with different maps.
|
||||
#define KEYMAP_STANDARD 0xFF
|
||||
#define KEYMAP_UK_WYSE_KB3926 0x01
|
||||
#define KEYMAP_JAPAN_OADG109 0x02
|
||||
#define KEYMAP_JAPAN_SANWA_SKBL1 0x04
|
||||
#define KEYMAP_NOT_ASSIGNED_4 0x08
|
||||
#define KEYMAP_NOT_ASSIGNED_5 0x10
|
||||
#define KEYMAP_NOT_ASSIGNED_6 0x20
|
||||
#define KEYMAP_UK_PERIBOARD_810 0x40
|
||||
#define KEYMAP_UK_OMOTON_K8508 0x80
|
||||
|
||||
public:
|
||||
// Prototypes.
|
||||
MZ5665(void);
|
||||
MZ5665(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, const char *fsPath);
|
||||
MZ5665(NVS *hdlNVS, HID *hdlHID, const char *fsPath);
|
||||
~MZ5665(void);
|
||||
bool createKeyMapFile(std::fstream &outFile);
|
||||
bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size);
|
||||
bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray);
|
||||
bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly);
|
||||
std::string getKeyMapFileName(void) { return(MZ5665IF_KEYMAP_FILE); };
|
||||
void getKeyMapHeaders(std::vector<std::string>& headerList);
|
||||
void getKeyMapTypes(std::vector<std::string>& typeList);
|
||||
bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start);
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(MZ5665IF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
void pushKeyToQueue(uint32_t key);
|
||||
IRAM_ATTR static void mzInterface( void * pvParameters );
|
||||
IRAM_ATTR static void hidInterface( void * pvParameters );
|
||||
void selectOption(uint8_t optionCode);
|
||||
uint32_t mapKey(uint16_t scanCode);
|
||||
bool loadKeyMap();
|
||||
bool saveKeyMap(void);
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// // Overload the base yield method to include suspension of the PS/2 Keyboard interface. This interface uses interrupts which are not mutex protected and clash with the
|
||||
// // WiFi API methods.
|
||||
// inline void yield(uint32_t delay)
|
||||
// {
|
||||
// // If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
// if(this->suspend)
|
||||
// {
|
||||
// // Suspend the keyboard interface.
|
||||
// Keyboard->suspend(true);
|
||||
//
|
||||
// // Use the base method logic.
|
||||
// KeyInterface::yield(delay);
|
||||
//
|
||||
// // Release the keyboard interface.
|
||||
// Keyboard->suspend(false);
|
||||
// } else
|
||||
// // Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
// {
|
||||
// KeyInterface::yield(delay);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Structure to encapsulate a single key map from PS/2 to MZ-5600/MZ-6500.
|
||||
typedef struct {
|
||||
uint8_t ps2KeyCode;
|
||||
uint8_t ps2Ctrl;
|
||||
uint8_t keyboardModel;
|
||||
uint8_t machine;
|
||||
uint8_t mzKey;
|
||||
uint8_t mzCtrl;
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[PS2TBL_MZ5665_MAXROWS];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to maintain the MZ-5600/MZ-6500 interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t activeKeyboardMap; // Model of keyboard a keymap entry is applicable to.
|
||||
uint8_t activeMachineModel; // Machine model a keymap entry is applicable to.
|
||||
} params;
|
||||
} t_mzConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_mzConfig mzConfig;
|
||||
|
||||
// Structure to manage the control signals signifying the state of the MZ-6500 keyboard.
|
||||
typedef struct {
|
||||
bool optionSelect; // Flag to indicate a user requested keyboard configuration option is being selected.
|
||||
uint8_t keyCtrl; // Keyboard state flag control.
|
||||
|
||||
std::string fsPath; // Path on the underlying filesystem where storage is mounted and accessible.
|
||||
t_keyMapEntry *kme; // Pointer to an array in memory to contain PS2 to MZ-6500 mapping values.
|
||||
int kmeRows; // Number of rows in the kme table.
|
||||
std::string keyMapFileName; // Name of file where extension or replacement key map entries are stored.
|
||||
} t_mzControl;
|
||||
|
||||
// Transmit buffer queue item.
|
||||
typedef struct {
|
||||
uint32_t keyCode; // 16bit, bits 8:0 represent the key, 9 if CTRL to be sent, 10 if ALT to be sent.
|
||||
} t_xmitQueueMessage;
|
||||
|
||||
// Thread handles - one per function, ie. HID interface and host target interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Control structure to control interaction and mapping of keys for the host.
|
||||
t_mzControl mzCtrl;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE mzMutex;
|
||||
|
||||
//
|
||||
// This mapping is for the UK Wyse KB-3926 PS/2 keyboard
|
||||
//
|
||||
t_keyMap PS2toMZ5665 = {
|
||||
{
|
||||
// HELP
|
||||
// COPY
|
||||
////PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
//{ PS2_KEY_F1, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 'v', 0x00, }, // SHIFT+F1
|
||||
//{ PS2_KEY_F2, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 'w', 0x00, }, // SHIFT+F2
|
||||
//{ PS2_KEY_F3, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 'x', 0x00, }, // SHIFT+F3
|
||||
//{ PS2_KEY_F4, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 'y', 0x00, }, // SHIFT+F4
|
||||
//{ PS2_KEY_F5, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 'z', 0x00, }, // SHIFT+F5
|
||||
//{ PS2_KEY_F1, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 'q', 0x00, }, // F1
|
||||
//{ PS2_KEY_F2, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 'r', 0x00, }, // F2
|
||||
//{ PS2_KEY_F3, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 's', 0x00, }, // F3
|
||||
//{ PS2_KEY_F4, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 't', 0x00, }, // F4
|
||||
//{ PS2_KEY_F5, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 'u', 0x00, }, // F5
|
||||
//{ PS2_KEY_F6, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0xEC, 0x00, }, // F6
|
||||
//{ PS2_KEY_F7, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0xEB, 0x00, }, // F7
|
||||
//{ PS2_KEY_F8, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0xE2, 0x00, }, // F8
|
||||
//{ PS2_KEY_F9, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0xE1, 0x00, }, // F9
|
||||
//{ PS2_KEY_F10, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // XFER
|
||||
//{ PS2_KEY_F11, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0xFE, 0x00, }, // HELP
|
||||
//{ PS2_KEY_F12, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // COPY
|
||||
//{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x09, 0x00, }, // TAB
|
||||
// Numeric keys.
|
||||
{ PS2_KEY_0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '0', 0x00, }, // 0
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '1', 0x00, }, // 1
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '2', 0x00, }, // 2
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '3', 0x00, }, // 3
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '4', 0x00, }, // 4
|
||||
{ PS2_KEY_5, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '5', 0x00, }, // 5
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '6', 0x00, }, // 6
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '7', 0x00, }, // 7
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '8', 0x00, }, // 8
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '9', 0x00, }, // 9
|
||||
// Punctuation keys.
|
||||
{ PS2_KEY_0, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, ')', 0x00, }, // Close Right Bracket )
|
||||
{ PS2_KEY_1, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '!', 0x00, }, // Exclamation
|
||||
{ PS2_KEY_2, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '"', 0x00, }, // Double quote.
|
||||
{ PS2_KEY_3, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0x23, 0x00, }, // Pound Sign -> Hash
|
||||
{ PS2_KEY_4, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '$', 0x00, }, // Dollar
|
||||
{ PS2_KEY_5, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '%', 0x00, }, // Percent
|
||||
{ PS2_KEY_6, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '^', 0x00, }, // Kappa
|
||||
{ PS2_KEY_7, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '&', 0x00, }, // Ampersand
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '*', 0x00, }, // Star
|
||||
{ PS2_KEY_9, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '(', 0x00, }, // Open Left Bracket (
|
||||
// ALPHA keys, lower and uppercase.
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_A, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'a', 0x00, }, // a
|
||||
{ PS2_KEY_A, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'A', 0x00, }, // A
|
||||
{ PS2_KEY_B, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'b', 0x00, }, // b
|
||||
{ PS2_KEY_B, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'B', 0x00, }, // B
|
||||
{ PS2_KEY_C, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'c', 0x00, }, // c
|
||||
{ PS2_KEY_C, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'C', 0x00, }, // C
|
||||
{ PS2_KEY_D, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'd', 0x00, }, // d
|
||||
{ PS2_KEY_D, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'D', 0x00, }, // D
|
||||
{ PS2_KEY_E, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'e', 0x00, }, // e
|
||||
{ PS2_KEY_E, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'E', 0x00, }, // E
|
||||
{ PS2_KEY_F, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'f', 0x00, }, // f
|
||||
{ PS2_KEY_F, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'F', 0x00, }, // F
|
||||
{ PS2_KEY_G, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'g', 0x00, }, // g
|
||||
{ PS2_KEY_G, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'G', 0x00, }, // G
|
||||
{ PS2_KEY_H, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'h', 0x00, }, // h
|
||||
{ PS2_KEY_H, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'H', 0x00, }, // H
|
||||
{ PS2_KEY_I, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'i', 0x00, }, // i
|
||||
{ PS2_KEY_I, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'I', 0x00, }, // I
|
||||
{ PS2_KEY_J, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'j', 0x00, }, // j
|
||||
{ PS2_KEY_J, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'J', 0x00, }, // J
|
||||
{ PS2_KEY_K, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'k', 0x00, }, // k
|
||||
{ PS2_KEY_K, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'K', 0x00, }, // K
|
||||
{ PS2_KEY_L, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'l', 0x00, }, // l
|
||||
{ PS2_KEY_L, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'L', 0x00, }, // L
|
||||
{ PS2_KEY_M, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'm', 0x00, }, // m
|
||||
{ PS2_KEY_M, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'M', 0x00, }, // M
|
||||
{ PS2_KEY_N, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'n', 0x00, }, // n
|
||||
{ PS2_KEY_N, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'N', 0x00, }, // N
|
||||
{ PS2_KEY_O, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'o', 0x00, }, // o
|
||||
{ PS2_KEY_O, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'O', 0x00, }, // O
|
||||
{ PS2_KEY_P, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'p', 0x00, }, // p
|
||||
{ PS2_KEY_P, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'P', 0x00, }, // P
|
||||
{ PS2_KEY_Q, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'q', 0x00, }, // q
|
||||
{ PS2_KEY_Q, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'Q', 0x00, }, // Q
|
||||
{ PS2_KEY_R, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'r', 0x00, }, // r
|
||||
{ PS2_KEY_R, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'R', 0x00, }, // R
|
||||
{ PS2_KEY_S, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 's', 0x00, }, // s
|
||||
{ PS2_KEY_S, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'S', 0x00, }, // S
|
||||
{ PS2_KEY_T, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 't', 0x00, }, // t
|
||||
{ PS2_KEY_T, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'T', 0x00, }, // T
|
||||
{ PS2_KEY_U, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'u', 0x00, }, // u
|
||||
{ PS2_KEY_U, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'U', 0x00, }, // U
|
||||
{ PS2_KEY_V, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'v', 0x00, }, // v
|
||||
{ PS2_KEY_V, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'V', 0x00, }, // V
|
||||
{ PS2_KEY_W, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'w', 0x00, }, // w
|
||||
{ PS2_KEY_W, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'W', 0x00, }, // W
|
||||
{ PS2_KEY_X, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'x', 0x00, }, // x
|
||||
{ PS2_KEY_X, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'X', 0x00, }, // X
|
||||
{ PS2_KEY_Y, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'y', 0x00, }, // y
|
||||
{ PS2_KEY_Y, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'Y', 0x00, }, // Y
|
||||
{ PS2_KEY_Z, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'z', 0x00, }, // z
|
||||
{ PS2_KEY_Z, PS2CTRL_CAPS, KEYMAP_STANDARD, MZ5665_ALL, 'Z', 0x00, }, // Z
|
||||
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ' ', 0x00, }, // Space
|
||||
{ PS2_KEY_COMMA, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '<', 0x00, }, // Less Than <
|
||||
{ PS2_KEY_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ',', 0x00, }, // Comma ,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, ':', 0x00, }, // Colon :
|
||||
{ PS2_KEY_SEMI, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ';', 0x00, }, // Semi-Colon ;
|
||||
{ PS2_KEY_DOT, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '>', 0x00, }, // Greater Than >
|
||||
{ PS2_KEY_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '.', 0x00, }, // Full stop .
|
||||
{ PS2_KEY_DIV, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '?', 0x00, }, // Question ?
|
||||
{ PS2_KEY_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '/', 0x00, }, // Divide /
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '_', 0x00, }, // Underscore
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '-', 0x00, },
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '@', 0x00, }, // At @
|
||||
{ PS2_KEY_APOS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '\'', 0x00, }, // Single quote '
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '{', 0x00, }, // Open Left Brace {
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '[', 0x00, }, // Open Left Square Bracket [
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '+', 0x00, }, // Plus +
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '=', 0x00, }, // Equal =
|
||||
{ PS2_KEY_CAPS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ' ', 0x00, }, // LOCK
|
||||
{ PS2_KEY_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x0D, 0x00, }, // ENTER/RETURN
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '}', 0x00, }, // Close Right Brace }
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ']', 0x00, }, // Close Right Square Bracket ]
|
||||
{ PS2_KEY_BACK, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '|', 0x00, }, //
|
||||
{ PS2_KEY_BACK, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '\\', 0x00, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_BTICK, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '`', 0x00, }, // Pipe
|
||||
{ PS2_KEY_BTICK, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '|', 0x00, }, // Back tick `
|
||||
{ PS2_KEY_HASH, PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, '~', 0x00, }, // Tilde has no mapping.
|
||||
{ PS2_KEY_HASH, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '#', 0x00, }, // Hash
|
||||
{ PS2_KEY_BS, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x08, 0x00, }, // Backspace
|
||||
{ PS2_KEY_ESC, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x1B, 0x00, }, // ESCape
|
||||
{ PS2_KEY_SCROLL, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, ' ', 0x00, }, // Not assigned.
|
||||
{ PS2_KEY_INSERT, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_INS, 0x00, }, // INSERT
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_CLR, 0x00, }, // CLR
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_HOME, 0x00, }, // HOME
|
||||
{ PS2_KEY_DELETE, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_DEL, 0x00, }, // DELETE
|
||||
{ PS2_KEY_END, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x11, 0x00, }, // END
|
||||
{ PS2_KEY_PGUP, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x0E, 0x00, }, // Roll Up.
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x0F, 0x00, }, // Roll Down
|
||||
{ PS2_KEY_UP_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_UP, 0x00, }, // Up Arrow
|
||||
{ PS2_KEY_L_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_LEFT, 0x00, }, // Left Arrow
|
||||
{ PS2_KEY_DN_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_DOWN, 0x00, }, // Down Arrow
|
||||
{ PS2_KEY_R_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, MZ5665_KEY_RIGHT, 0x00, }, // Right Arrow
|
||||
{ PS2_KEY_NUM, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // Not assigned.
|
||||
// GRPH (Alt Gr)
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_0, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xFA, 0x00, }, // GRPH+0
|
||||
{ PS2_KEY_1, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF1, 0x00, }, // GRPH+1
|
||||
{ PS2_KEY_2, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF2, 0x00, }, // GRPH+2
|
||||
{ PS2_KEY_3, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF3, 0x00, }, // GRPH+3
|
||||
{ PS2_KEY_4, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF4, 0x00, }, // GRPH+4
|
||||
{ PS2_KEY_5, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF5, 0x00, }, // GRPH+5
|
||||
{ PS2_KEY_6, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF6, 0x00, }, // GRPH+6
|
||||
{ PS2_KEY_7, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF7, 0x00, }, // GRPH+7
|
||||
{ PS2_KEY_8, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF8, 0x00, }, // GRPH+8
|
||||
{ PS2_KEY_9, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF9, 0x00, }, // GRPH+9
|
||||
{ PS2_KEY_A, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x7F, 0x00, }, // GRPH+A
|
||||
{ PS2_KEY_B, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x84, 0x00, }, // GRPH+B
|
||||
{ PS2_KEY_C, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x82, 0x00, }, // GRPH+C
|
||||
{ PS2_KEY_D, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xEA, 0x00, }, // GRPH+D
|
||||
{ PS2_KEY_E, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE2, 0x00, }, // GRPH+E
|
||||
{ PS2_KEY_F, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xEB, 0x00, }, // GRPH+F
|
||||
{ PS2_KEY_G, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xEC, 0x00, }, // GRPH+G
|
||||
{ PS2_KEY_H, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xED, 0x00, }, // GRPH+H
|
||||
{ PS2_KEY_I, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE7, 0x00, }, // GRPH+I
|
||||
{ PS2_KEY_J, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xEE, 0x00, }, // GRPH+J
|
||||
{ PS2_KEY_K, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xEF, 0x00, }, // GRPH+K
|
||||
{ PS2_KEY_L, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x8E, 0x00, }, // GRPH+L
|
||||
{ PS2_KEY_M, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x86, 0x00, }, // GRPH+M
|
||||
{ PS2_KEY_N, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x85, 0x00, }, // GRPH+N
|
||||
{ PS2_KEY_O, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xF0, 0x00, }, // GRPH+O
|
||||
{ PS2_KEY_P, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x8D, 0x00, }, // GRPH+P
|
||||
{ PS2_KEY_Q, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE0, 0x00, }, // GRPH+Q
|
||||
{ PS2_KEY_R, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE3, 0x00, }, // GRPH+R
|
||||
{ PS2_KEY_S, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE9, 0x00, }, // GRPH+S
|
||||
{ PS2_KEY_T, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE4, 0x00, }, // GRPH+T
|
||||
{ PS2_KEY_U, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE6, 0x00, }, // GRPH+U
|
||||
{ PS2_KEY_V, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x83, 0x00, }, // GRPH+V
|
||||
{ PS2_KEY_W, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE1, 0x00, }, // GRPH+W
|
||||
{ PS2_KEY_X, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x81, 0x00, }, // GRPH+X
|
||||
{ PS2_KEY_Y, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE5, 0x00, }, // GRPH+Y
|
||||
{ PS2_KEY_Z, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x80, 0x00, }, // GRPH+Z
|
||||
{ PS2_KEY_COMMA, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x87, 0x00, }, // GRPH+,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x89, 0x00, }, // GRPH+;
|
||||
{ PS2_KEY_DOT, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x88, 0x00, }, // GRPH+.
|
||||
{ PS2_KEY_DIV, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xFE, 0x00, }, // GRPH+/
|
||||
{ PS2_KEY_MINUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x8C, 0x00, }, // GRPH+-
|
||||
{ PS2_KEY_APOS, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x8A, 0x00, }, // GRPH+'
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xFC, 0x00, }, // GRPH+[
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0xE8, 0x00, }, // GRPH+]
|
||||
{ PS2_KEY_BACK, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x90, 0x00, }, // GRPH+Backslash
|
||||
{ PS2_KEY_KP0, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x8F, 0x00, }, // GRPH+Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x99, 0x00, }, // GRPH+Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x92, 0x00, }, // GRPH+Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x98, 0x00, }, // GRPH+Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x95, 0x00, }, // GRPH+Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x96, 0x00, }, // GRPH+Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x94, 0x00, }, // GRPH+Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x9A, 0x00, }, // GRPH+Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x93, 0x00, }, // GRPH+Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x97, 0x00, }, // GRPH+Keypad 9
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x91, 0x00, }, // GRPH+Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x9D, 0x00, }, // GRPH+Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x9C, 0x00, }, // GRPH+Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x9B, 0x00, }, // GRPH+Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x9E, 0x00, }, // GRPH+Keypad Divide /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x90, 0x00, }, // GRPH+Keypad Ebter /
|
||||
// KANA (Alt)
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_0, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA6, 0x00, }, // KANA+SHIFT+0
|
||||
{ PS2_KEY_0, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDC, 0x00, }, // KANA+0
|
||||
{ PS2_KEY_1, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC7, 0x00, }, // KANA+1
|
||||
{ PS2_KEY_2, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xCC, 0x00, }, // KANA+2
|
||||
{ PS2_KEY_3, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA7, 0x00, }, // KANA+SHIFT+3
|
||||
{ PS2_KEY_3, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB1, 0x00, }, // KANA+3
|
||||
{ PS2_KEY_4, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA9, 0x00, }, // KANA+SHIFT+4
|
||||
{ PS2_KEY_4, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB3, 0x00, }, // KANA+4
|
||||
{ PS2_KEY_5, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAA, 0x00, }, // KANA+SHIFT+5
|
||||
{ PS2_KEY_5, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB4, 0x00, }, // KANA+5
|
||||
{ PS2_KEY_6, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAB, 0x00, }, // KANA+SHIFT+6
|
||||
{ PS2_KEY_6, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB5, 0x00, }, // KANA+6
|
||||
{ PS2_KEY_7, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAC, 0x00, }, // KANA+SHIFT+7
|
||||
{ PS2_KEY_7, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD4, 0x00, }, // KANA+7
|
||||
{ PS2_KEY_8, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAD, 0x00, }, // KANA+SHIFT+8
|
||||
{ PS2_KEY_8, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD5, 0x00, }, // KANA+8
|
||||
{ PS2_KEY_9, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAE, 0x00, }, // KANA+SHIFT+9
|
||||
{ PS2_KEY_9, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD6, 0x00, }, // KANA+9
|
||||
{ PS2_KEY_A, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC1, 0x00, }, // KANA+A
|
||||
{ PS2_KEY_B, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBA, 0x00, }, // KANA+B
|
||||
{ PS2_KEY_C, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBF, 0x00, }, // KANA+C
|
||||
{ PS2_KEY_D, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBC, 0x00, }, // KANA+D
|
||||
{ PS2_KEY_E, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA8, 0x00, }, // KANA+SHIFT+E
|
||||
{ PS2_KEY_E, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB2, 0x00, }, // KANA+E
|
||||
{ PS2_KEY_F, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xCA, 0x00, }, // KANA+F
|
||||
{ PS2_KEY_G, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB7, 0x00, }, // KANA+G
|
||||
{ PS2_KEY_H, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB8, 0x00, }, // KANA+H
|
||||
{ PS2_KEY_I, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC6, 0x00, }, // KANA+I
|
||||
{ PS2_KEY_J, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xCF, 0x00, }, // KANA+J
|
||||
{ PS2_KEY_K, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC9, 0x00, }, // KANA+K
|
||||
{ PS2_KEY_L, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD8, 0x00, }, // KANA+L
|
||||
{ PS2_KEY_M, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD3, 0x00, }, // KANA+M
|
||||
{ PS2_KEY_N, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD0, 0x00, }, // KANA+N
|
||||
{ PS2_KEY_O, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD7, 0x00, }, // KANA+O
|
||||
{ PS2_KEY_P, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBE, 0x00, }, // KANA+P
|
||||
{ PS2_KEY_Q, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC0, 0x00, }, // KANA+Q
|
||||
{ PS2_KEY_R, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBD, 0x00, }, // KANA+R
|
||||
{ PS2_KEY_S, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC4, 0x00, }, // KANA+S
|
||||
{ PS2_KEY_T, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xB6, 0x00, }, // KANA+T
|
||||
{ PS2_KEY_U, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC5, 0x00, }, // KANA+U
|
||||
{ PS2_KEY_V, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xCB, 0x00, }, // KANA+V
|
||||
{ PS2_KEY_W, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC3, 0x00, }, // KANA+W
|
||||
{ PS2_KEY_X, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xBB, 0x00, }, // KANA+X
|
||||
{ PS2_KEY_Y, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDD, 0x00, }, // KANA+Y
|
||||
{ PS2_KEY_Z, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xAF, 0x00, }, // KANA+SHIFT+Z
|
||||
{ PS2_KEY_Z, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC2, 0x00, }, // KANA+Z
|
||||
{ PS2_KEY_COMMA, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA4, 0x00, }, // KANA+SHIFT+,
|
||||
{ PS2_KEY_COMMA, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xC8, 0x00, }, // KANA+,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDA, 0x00, }, // KANA+;
|
||||
{ PS2_KEY_DOT, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA1, 0x00, }, // KANA+SHIFT+.
|
||||
{ PS2_KEY_DOT, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD9, 0x00, }, // KANA+.
|
||||
{ PS2_KEY_DIV, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA5, 0x00, }, // KANA+SHIFT+/
|
||||
{ PS2_KEY_DIV, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD2, 0x00, }, // KANA+/
|
||||
{ PS2_KEY_MINUS, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xCE, 0x00, }, // KANA+-
|
||||
{ PS2_KEY_APOS, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDE, 0x00, }, // KANA+'
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA2, 0x00, }, // KANA+SHIFT+[
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDF, 0x00, }, // KANA+[
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0xA3, 0x00, }, // KANA+SHIFT+]
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xD1, 0x00, }, // KANA+]
|
||||
{ PS2_KEY_BACK, PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0xDB, 0x00, }, // KANA+Backslash
|
||||
{ PS2_KEY_BS, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, MZ5665_ALL, 0x12, 0x00, }, // KANA+SHIFT+Backspace
|
||||
// Keypad.
|
||||
{ PS2_KEY_KP0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '0', 0x00, }, // Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '1', 0x00, }, // Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '2', 0x00, }, // Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '3', 0x00, }, // Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '4', 0x00, }, // Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '5', 0x00, }, // Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '6', 0x00, }, // Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '7', 0x00, }, // Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '8', 0x00, }, // Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '9', 0x00, }, // Keypad 9
|
||||
{ PS2_KEY_KP_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, ',', 0x00, }, // Keypad Comma ,
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '.', 0x00, }, // Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '+', 0x00, }, // Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '-', 0x00, }, // Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '*', 0x00, }, // Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, '/', 0x00, }, // Keypad Divide /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x0D, 0x00, }, // Keypad Ebter /
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine MZ5665 Data MZ5665 Ctrl (Flags to Set).
|
||||
// Special keys.
|
||||
{ PS2_KEY_PRTSCR, PS2CTRL_FUNC, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // ARGO KEY
|
||||
{ PS2_KEY_PAUSE, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x03, 0x00, }, // BREAK KEY
|
||||
{ PS2_KEY_L_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // GRAPH KEY
|
||||
//{ PS2_KEY_L_ALT, PS2CTRL_FUNC | PS2CTRL_KANA, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // KJ1 Sentence
|
||||
//{ PS2_KEY_R_ALT, PS2CTRL_FUNC | PS2CTRL_GRAPH, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // KJ2 Transform
|
||||
{ PS2_KEY_R_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // KANA KEY
|
||||
{ PS2_KEY_MENU, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // Not assigned.
|
||||
// Modifiers are last, only being selected if an earlier match isnt made.
|
||||
{ PS2_KEY_L_SHIFT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, },
|
||||
{ PS2_KEY_R_SHIFT, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, },
|
||||
{ PS2_KEY_L_CTRL, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, },
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, }, // Map to Control
|
||||
{ 0, PS2CTRL_NONE, KEYMAP_STANDARD, MZ5665_ALL, 0x00, 0x00, },
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // MZ5665_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/Mouse.h
|
||||
151
main/include/Mouse.h
Normal file
151
main/include/Mouse.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: Mouse.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the PS/2 Mouse to Sharp Host interface logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
// Updates to reflect moving functionality into the HID and to support
|
||||
// Bluetooth as a primary mouse or secondary mouse.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MOUSE_H
|
||||
#define MOUSE_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "HID.h"
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the Mouse interface.
|
||||
class Mouse : public KeyInterface {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define MOUSEIF_VERSION 1.02
|
||||
#define MAX_MOUSE_XMIT_KEY_BUF 128
|
||||
#define BITBANG_UART_BIT_TIME 208UL
|
||||
|
||||
public:
|
||||
|
||||
// Prototypes.
|
||||
Mouse(void);
|
||||
Mouse(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
Mouse(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, bool secondaryIf);
|
||||
Mouse(NVS *hdlNVShdlHID, HID *hdlHID);
|
||||
~Mouse(void);
|
||||
void getMouseConfigTypes(std::vector<std::string>& typeList);
|
||||
bool getMouseSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool setMouseConfigValue(std::string paramName, std::string paramValue);
|
||||
void mouseReceiveData(HID::t_mouseMessageElement mouseMessage);
|
||||
bool persistConfig(void);
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(MOUSEIF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
IRAM_ATTR static void hostInterface( void * pvParameters );
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// Structure to maintain mouse interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
// PS/2 Mouse data Adjustment and filtering options.
|
||||
//
|
||||
enum HID::HID_MOUSE_RESOLUTION resolution;
|
||||
enum HID::HID_MOUSE_SCALING scaling;
|
||||
enum HID::HID_MOUSE_SAMPLING sampleRate;
|
||||
} mouse;
|
||||
|
||||
struct {
|
||||
// Host data for adjustment and configuration.
|
||||
enum HID::HID_MOUSE_HOST_SCALING scaling;
|
||||
} host;
|
||||
|
||||
struct {
|
||||
} params;
|
||||
} t_mouseConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_mouseConfig mouseConfig;
|
||||
|
||||
// Structure to manage the Mouse control variables signifying the state of the Mouse.
|
||||
typedef struct {
|
||||
} t_msControl;
|
||||
|
||||
// Mouse Control variables.
|
||||
volatile t_msControl msCtrl;
|
||||
|
||||
// Structure to manage the Sharp host control variables which define control and data mapping of the host interface and data sent.
|
||||
//
|
||||
typedef struct {
|
||||
#ifdef CONFIG_HOST_HW_UART
|
||||
int uartNum;
|
||||
int uartBufferSize;
|
||||
int uartQueueSize;
|
||||
#endif
|
||||
bool secondaryIf; // Mouse runs in tandem with a keyboard interface.
|
||||
|
||||
// Data adjustment and processing options applied to the PS/2 data.
|
||||
bool updated;
|
||||
} t_hostControl;
|
||||
|
||||
// Host Control variables.
|
||||
volatile t_hostControl hostControl;
|
||||
|
||||
// PS/2 to HOST serialiser buffer item.
|
||||
typedef struct {
|
||||
uint8_t xPos;
|
||||
uint8_t yPos;
|
||||
uint8_t status;
|
||||
uint8_t wheel;
|
||||
bool valid;
|
||||
} t_xmitMessage;
|
||||
|
||||
// Create an object for storing the data to be sent to the Host. This data has already been converted and adjusted from the incoming PS/2 message.
|
||||
t_xmitMessage xmitMsg;
|
||||
|
||||
// Thread handles - one per function, ie. ps/2 interface, host target interface, wifi interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE x1Mutex;
|
||||
};
|
||||
|
||||
#endif // MOUSE_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/NVS.h
|
||||
162
main/include/NVS.h
Normal file
162
main/include/NVS.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: NVS.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Class definition to encapsulate the Espressif Non Volatile Storage into a thread safe
|
||||
// object, The underlying API is supposed to be thread safe but experience has shown
|
||||
// that two threads, each with there own handle can cause a lockup.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef NVS_H
|
||||
#define NVS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Define a virtual class which acts as the base and specification of all super classes forming host
|
||||
// interface objects.
|
||||
class NVS {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define NVS_VERSION 1.01
|
||||
|
||||
public:
|
||||
|
||||
// Prototypes.
|
||||
NVS(void);
|
||||
NVS(std::string keyName);
|
||||
virtual ~NVS(void) {};
|
||||
void eraseAll(void);
|
||||
void init(void);
|
||||
bool takeMutex(void);
|
||||
void giveMutex(void);
|
||||
// Persistence.
|
||||
bool open(std::string keyName);
|
||||
bool persistData(const char *key, void *pData, uint32_t size);
|
||||
bool retrieveData(const char *key, void *pData, uint32_t size);
|
||||
bool commitData(void);
|
||||
|
||||
// Helper method to identify the sub class, this is used in non volatile key management.
|
||||
// Warning: This method wont work if optimisation for size is enabled on the compiler.
|
||||
const char *getClassName(const std::string& prettyFunction)
|
||||
{
|
||||
// First find the CLASS :: METHOD seperation.
|
||||
size_t colons = prettyFunction.find("::");
|
||||
|
||||
// None, then this is not a class.
|
||||
if (colons == std::string::npos)
|
||||
return "::";
|
||||
|
||||
// Split out the class name.
|
||||
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
|
||||
size_t end = colons - begin;
|
||||
|
||||
// Return the name.
|
||||
return(prettyFunction.substr(begin,end).c_str());
|
||||
}
|
||||
|
||||
// Helper method to change a file extension.
|
||||
void replaceExt(std::string& fileName, const std::string& newExt)
|
||||
{
|
||||
// Locals.
|
||||
std::string::size_type extPos = fileName.rfind('.', fileName.length());
|
||||
|
||||
if(extPos != std::string::npos)
|
||||
{
|
||||
fileName.replace(extPos+1, newExt.length(), newExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
// Method to return the class version number.
|
||||
virtual float version(void)
|
||||
{
|
||||
return(NVS_VERSION);
|
||||
}
|
||||
|
||||
// Method to return the name of the class.
|
||||
virtual std::string ifName(void)
|
||||
{
|
||||
return(nvsCtrl.nvsClassName);
|
||||
}
|
||||
|
||||
// Method to return the name of the nvs key.
|
||||
virtual std::string keyName(void)
|
||||
{
|
||||
return(nvsCtrl.nvsKeyName);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
// Structure to maintain an active setting for the LED. The LED control thread uses these values to effect the required lighting of the LED.
|
||||
typedef struct {
|
||||
// Handle to the persistent storage api.
|
||||
nvs_handle_t nvsHandle;
|
||||
|
||||
// Name of the class for this instantiation.
|
||||
std::string nvsClassName;
|
||||
|
||||
// Name of the key under which NVS was opened.
|
||||
std::string nvsKeyName;
|
||||
|
||||
// Mutex to block access to limit one thread at a time.
|
||||
SemaphoreHandle_t mutexInternal;
|
||||
} t_nvsControl;
|
||||
|
||||
// Var to store all NVS control variables.
|
||||
t_nvsControl nvsCtrl;
|
||||
|
||||
};
|
||||
#endif // NVS_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/PC9801.h
|
||||
529
main/include/PC9801.h
Normal file
529
main/include/PC9801.h
Normal file
@@ -0,0 +1,529 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: PC9801.h
|
||||
// Created: Apr 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the NEC PC-9801 to HID (PS/2, Bluetooth) interface logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Apr 2022 - Initial write.
|
||||
// v1.01 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
//
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PC9801_H
|
||||
#define PC9801_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the NEC PC-9801 interface.
|
||||
class PC9801 : public KeyInterface {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define PC9801IF_VERSION 1.00
|
||||
#define PC9801IF_KEYMAP_FILE "PC9801_KeyMap.BIN"
|
||||
#define MAX_PC9801_XMIT_KEY_BUF 16
|
||||
#define MAX_PC9801_RCV_KEY_BUF 16
|
||||
|
||||
// NEC PC-9801 Key control bit mask.
|
||||
#define PC9801_CTRL_SHIFT ((unsigned char) (1 << 5))
|
||||
#define PC9801_CTRL_RELEASESHIFT ((unsigned char) (1 << 4))
|
||||
#define PC9801_CTRL_CTRL ((unsigned char) (1 << 3))
|
||||
#define PC9801_CTRL_GRAPH ((unsigned char) (1 << 2))
|
||||
#define PC9801_CTRL_CAPS ((unsigned char) (1 << 1))
|
||||
#define PC9801_CTRL_KANA ((unsigned char) (1 << 0))
|
||||
#define PC9801_CTRL_NONE 0x00
|
||||
|
||||
// Special key definition.
|
||||
// #define PC9801_KEY_UP 0x1E // ↑
|
||||
// #define PC9801_KEY_DOWN 0x1F // ↓
|
||||
// #define PC9801_KEY_LEFT 0x1D // ←
|
||||
// #define PC9801_KEY_RIGHT 0x1C // → →
|
||||
// #define PC9801_KEY_INS 0x12 // INS
|
||||
// #define PC9801_KEY_DEL 0x08 // DEL
|
||||
// #define PC9801_KEY_CLR 0x0C // CLR
|
||||
// #define PC9801_KEY_HOME 0x0B // HOME
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2CTRL_NONE 0x00 // No keys active = 0
|
||||
#define PS2CTRL_SHIFT 0x01 // Shfit Key active = 1
|
||||
#define PS2CTRL_CTRL 0x02 // Ctrl Key active = 1
|
||||
#define PS2CTRL_CAPS 0x04 // CAPS active = 1
|
||||
#define PS2CTRL_KANA 0x08 // KANA active = 1
|
||||
#define PS2CTRL_GRAPH 0x10 // GRAPH active = 1
|
||||
#define PS2CTRL_GUI 0x20 // GUI Key active = 1
|
||||
#define PS2CTRL_FUNC 0x40 // Special Function Keys active = 1
|
||||
#define PS2CTRL_BREAK 0x80 // BREAK Key active = 1
|
||||
#define PS2CTRL_EXACT 0x80 // EXACT Match active = 1
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to extract the PC-9801 key code and control data.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> PC-9801 Key Code + Ctrl Data
|
||||
#define PS2TBL_PC9801_MAXCOLS 6
|
||||
#define PS2TBL_PC9801_MAXROWS 131
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to extract the NEC PC-9801 key code and control data.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> NEC PC-9801 Key Code + Ctrl Data
|
||||
|
||||
// Keyboard mapping table column names.
|
||||
#define PS2TBL_PS2KEYCODE_NAME "PS/2 KeyCode"
|
||||
#define PS2TBL_PS2CTRL_NAME "PS/2 Control Key"
|
||||
#define PS2TBL_KEYBOARDMODEL_NAME "For Keyboard"
|
||||
#define PS2TBL_MACHINE_NAME "For Host Model"
|
||||
#define PS2TBL_PC9801_KEYCODE_NAME "PC9801 KeyCode"
|
||||
#define PS2TBL_PC9801__CTRL_NAME "PC9801 Control Key"
|
||||
|
||||
// Keyboard mapping table column types.
|
||||
#define PS2TBL_PS2KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PS2CTRL_TYPE "custom_cbp_ps2ctrl"
|
||||
#define PS2TBL_KEYBOARDMODEL_TYPE "custom_cbp_keybmodel"
|
||||
#define PS2TBL_MACHINE_TYPE "custom_cbp_machine"
|
||||
#define PS2TBL_PC9801_KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PC9801_CTRL_TYPE "custom_cbn_x1ctrl"
|
||||
|
||||
// Keyboard mapping table select list for PS2CTRL.
|
||||
#define PS2TBL_PS2CTRL_SEL_NONE "NONE"
|
||||
#define PS2TBL_PS2CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PS2TBL_PS2CTRL_SEL_CTRL "CTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_CAPS "CAPS"
|
||||
#define PS2TBL_PS2CTRL_SEL_KANA "KANA"
|
||||
#define PS2TBL_PS2CTRL_SEL_GRAPH "GRAPH"
|
||||
#define PS2TBL_PS2CTRL_SEL_GUI "GUI"
|
||||
#define PS2TBL_PS2CTRL_SEL_FUNC "FUNC"
|
||||
#define PS2TBL_PS2CTRL_SEL_EXACT "EXACT"
|
||||
|
||||
// Keyboard mapping table select list for target machine.
|
||||
#define PC9801_SEL_ALL "ALL"
|
||||
#define PC9801_SEL_ORIG "ORIGINAL"
|
||||
|
||||
// Keyboard mapping table select list for Model of keyboard.
|
||||
#define KEYMAP_SEL_STANDARD "ALL"
|
||||
#define KEYMAP_SEL_UK_WYSE_KB3926 "UK_WYSE_KB3926"
|
||||
#define KEYMAP_SEL_JAPAN_OADG109 "JAPAN_OADG109"
|
||||
#define KEYMAP_SEL_JAPAN_SANWA_SKBL1 "JAPAN_SANWA_SKBL1"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_4 "KEYBOARD_4"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_5 "KEYBOARD_5"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_6 "KEYBOARD_6"
|
||||
#define KEYMAP_SEL_UK_PERIBOARD_810 "UK_PERIBOARD_810"
|
||||
#define KEYMAP_SEL_UK_OMOTON_K8508 "UK_OMOTON_K8508"
|
||||
|
||||
// Keyboard mapping table select list for PC9801 Control codes.
|
||||
#define PC9801_CTRL_SEL_GRAPH "GRAPH"
|
||||
#define PC9801_CTRL_SEL_CAPS "CAPS"
|
||||
#define PC9801_CTRL_SEL_KANA "KANA"
|
||||
#define PC9801_CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PC9801_CTRL_SEL_CTRL "CTRL"
|
||||
|
||||
// The NEC PC-9801 Series was released over a number of years and each iteration added changes/updates. In order to cater for differences, it is possible to assign a key mapping
|
||||
// to a specific machine type(s) or all of the series by adding the flags below into the mapping table.
|
||||
#define PC9801_ALL 0xFF
|
||||
|
||||
// Keyboard models. The base on which this interface was created was a Wyse KB3926 PS/2 Keyboard and this is deemed STANDARD. Other models need to insert difference maps
|
||||
// prior to the STANDARD entry along with the keyboard model so that it is processed first thus allowing differing keyboards with different maps.
|
||||
#define KEYMAP_STANDARD 0xFF
|
||||
#define KEYMAP_UK_WYSE_KB3926 0x01
|
||||
#define KEYMAP_JAPAN_OADG109 0x02
|
||||
#define KEYMAP_JAPAN_SANWA_SKBL1 0x04
|
||||
#define KEYMAP_NOT_ASSIGNED_4 0x08
|
||||
#define KEYMAP_NOT_ASSIGNED_5 0x10
|
||||
#define KEYMAP_NOT_ASSIGNED_6 0x20
|
||||
#define KEYMAP_UK_PERIBOARD_810 0x40
|
||||
#define KEYMAP_UK_OMOTON_K8508 0x80
|
||||
|
||||
// PC-9801 Scan codes - PS2 codes along with function keys (SHIFT, CTRL etc) are mapped to the X68000 scan codes below.
|
||||
#define PC9801_KEY_ESC 0x00
|
||||
#define PC9801_KEY_0 0x0A
|
||||
#define PC9801_KEY_1 0x01
|
||||
#define PC9801_KEY_2 0x02
|
||||
#define PC9801_KEY_3 0x03
|
||||
#define PC9801_KEY_4 0x04
|
||||
#define PC9801_KEY_5 0x05
|
||||
#define PC9801_KEY_6 0x06
|
||||
#define PC9801_KEY_7 0x07
|
||||
#define PC9801_KEY_8 0x08
|
||||
#define PC9801_KEY_9 0x09
|
||||
#define PC9801_KEY_A 0x1D
|
||||
#define PC9801_KEY_B 0x2D
|
||||
#define PC9801_KEY_C 0x2B
|
||||
#define PC9801_KEY_D 0x1F
|
||||
#define PC9801_KEY_E 0x12
|
||||
#define PC9801_KEY_F 0x20
|
||||
#define PC9801_KEY_G 0x21
|
||||
#define PC9801_KEY_H 0x22
|
||||
#define PC9801_KEY_I 0x17
|
||||
#define PC9801_KEY_J 0x23
|
||||
#define PC9801_KEY_K 0x24
|
||||
#define PC9801_KEY_L 0x25
|
||||
#define PC9801_KEY_M 0x2F
|
||||
#define PC9801_KEY_N 0x2E
|
||||
#define PC9801_KEY_O 0x18
|
||||
#define PC9801_KEY_P 0x19
|
||||
#define PC9801_KEY_Q 0x10
|
||||
#define PC9801_KEY_R 0x13
|
||||
#define PC9801_KEY_S 0x1E
|
||||
#define PC9801_KEY_T 0x14
|
||||
#define PC9801_KEY_U 0x16
|
||||
#define PC9801_KEY_V 0x2C
|
||||
#define PC9801_KEY_W 0x11
|
||||
#define PC9801_KEY_X 0x2A
|
||||
#define PC9801_KEY_Y 0x15
|
||||
#define PC9801_KEY_Z 0x29
|
||||
#define PC9801_KEY_AT 0x1A // Requires SHIFT
|
||||
#define PC9801_KEY_MINUS 0x0B
|
||||
#define PC9801_KEY_CIRCUMFLEX 0x0C
|
||||
#define PC9801_KEY_YEN 0x0D
|
||||
#define PC9801_KEY_BS 0x0E
|
||||
#define PC9801_KEY_TAB 0x0F
|
||||
#define PC9801_KEY_OPEN_SQ 0x1A
|
||||
#define PC9801_KEY_CLOSE_SQ 0x1B
|
||||
#define PC9801_KEY_RETURN 0x1C
|
||||
#define PC9801_KEY_SEMI 0x26
|
||||
#define PC9801_KEY_COLON 0x27
|
||||
#define PC9801_KEY_COMMA 0x30
|
||||
#define PC9801_KEY_DOT 0x31
|
||||
#define PC9801_KEY_DIV 0x32
|
||||
#define PC9801_KEY_UNDERLINE 0x0D // Requires SHIFT
|
||||
#define PC9801_KEY_SPACE 0x34
|
||||
#define PC9801_KEY_HOME 0x3E
|
||||
#define PC9801_KEY_ROLLUP 0x36
|
||||
#define PC9801_KEY_ROLLDN 0x37
|
||||
#define PC9801_KEY_UNDO 0x3 // Not known3
|
||||
#define PC9801_KEY_L_ARROW 0x3B
|
||||
#define PC9801_KEY_UP_ARROW 0x3A
|
||||
#define PC9801_KEY_R_ARROW 0x3C
|
||||
#define PC9801_KEY_DN_ARROW 0x3D
|
||||
#define PC9801_KEY_CLR 0x3F // Not known
|
||||
#define PC9801_KEY_KP0 0x4E
|
||||
#define PC9801_KEY_KP1 0x4A
|
||||
#define PC9801_KEY_KP2 0x4B
|
||||
#define PC9801_KEY_KP3 0x4C
|
||||
#define PC9801_KEY_KP4 0x46
|
||||
#define PC9801_KEY_KP5 0x47
|
||||
#define PC9801_KEY_KP6 0x48
|
||||
#define PC9801_KEY_KP7 0x42
|
||||
#define PC9801_KEY_KP8 0x43
|
||||
#define PC9801_KEY_KP9 0x44
|
||||
#define PC9801_KEY_KP_DIV 0x41
|
||||
#define PC9801_KEY_KP_TIMES 0x45
|
||||
#define PC9801_KEY_KP_MINUS 0x4D
|
||||
#define PC9801_KEY_KP_PLUS 0x49
|
||||
#define PC9801_KEY_KP_EQUAL 0x4D
|
||||
#define PC9801_KEY_KP_ENTER 0x1C
|
||||
#define PC9801_KEY_KP_COMMA 0x4F
|
||||
#define PC9801_KEY_KP_DOT 0x50
|
||||
#define PC9801_KEY_SYMBOL 0x52 // Not known
|
||||
#define PC9801_KEY_HELP 0x3F
|
||||
#define PC9801_KEY_CAPS 0x71
|
||||
#define PC9801_KEY_INS 0x38
|
||||
#define PC9801_KEY_DEL 0x39
|
||||
#define PC9801_KEY_BREAK 0x60 // Stop
|
||||
#define PC9801_KEY_COPY 0x61
|
||||
#define PC9801_KEY_SHIFT 0x70
|
||||
#define PC9801_KEY_R_SHIFT 0x7D
|
||||
#define PC9801_KEY_CTRL 0x74
|
||||
#define PC9801_KEY_GRAPH 0x73
|
||||
#define PC9801_KEY_XFER 0x35
|
||||
#define PC9801_KEY_NFER 0x51
|
||||
#define PC9801_KEY_KATAKANA 0x72
|
||||
#define PC9801_KEY_ROMAJI 0x33
|
||||
#define PC9801_KEY_F1 0x62
|
||||
#define PC9801_KEY_F2 0x63
|
||||
#define PC9801_KEY_F3 0x64
|
||||
#define PC9801_KEY_F4 0x65
|
||||
#define PC9801_KEY_F5 0x66
|
||||
#define PC9801_KEY_F6 0x67
|
||||
#define PC9801_KEY_F7 0x68
|
||||
#define PC9801_KEY_F8 0x69
|
||||
#define PC9801_KEY_F9 0x6A
|
||||
#define PC9801_KEY_F10 0x6B
|
||||
#define PC9801_KEY_F11 0x52
|
||||
#define PC9801_KEY_F12 0x53
|
||||
#define PC9801_KEY_F13 0x54
|
||||
#define PC9801_KEY_F14 0x55
|
||||
#define PC9801_KEY_F15 0x56
|
||||
#define PC9801_KEY_NULL 0xFF
|
||||
|
||||
public:
|
||||
// Prototypes.
|
||||
PC9801(void);
|
||||
PC9801(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, const char *fsPath);
|
||||
PC9801(NVS *hdlNVS, HID *hdlHID, const char *fsPath);
|
||||
~PC9801(void);
|
||||
bool createKeyMapFile(std::fstream &outFile);
|
||||
bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size);
|
||||
bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray);
|
||||
bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly);
|
||||
std::string getKeyMapFileName(void) { return(PC9801IF_KEYMAP_FILE); };
|
||||
void getKeyMapHeaders(std::vector<std::string>& headerList);
|
||||
void getKeyMapTypes(std::vector<std::string>& typeList);
|
||||
bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start);
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(PC9801IF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
IRAM_ATTR void pushKeyToQueue(uint32_t key);
|
||||
IRAM_ATTR void pushHostCmdToQueue(uint8_t cmd);
|
||||
IRAM_ATTR static void pcInterface( void * pvParameters );
|
||||
IRAM_ATTR static void hidInterface( void * pvParameters );
|
||||
void selectOption(uint8_t optionCode);
|
||||
uint32_t mapKey(uint16_t scanCode);
|
||||
bool loadKeyMap();
|
||||
bool saveKeyMap(void);
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// Structure to encapsulate a single key map from PS/2 to NEC PC-9801
|
||||
typedef struct {
|
||||
uint8_t ps2KeyCode;
|
||||
uint8_t ps2Ctrl;
|
||||
uint8_t keyboardModel;
|
||||
uint8_t machine;
|
||||
uint8_t pcKey;
|
||||
uint8_t pcCtrl;
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[PS2TBL_PC9801_MAXROWS];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to maintain the NEC PC-9801 interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t activeKeyboardMap; // Model of keyboard a keymap entry is applicable to.
|
||||
uint8_t activeMachineModel; // Machine model a keymap entry is applicable to.
|
||||
bool useOnlyPersisted; // Flag to indicate wether the inbuilt keymap array should be combined with persisted values or the inbuilt array is ignored and only persisted values used.
|
||||
} params;
|
||||
} t_pcConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_pcConfig pcConfig;
|
||||
|
||||
// Structure to manage the control signals signifying the state of the NEC PC-9801 keyboard.
|
||||
typedef struct {
|
||||
uint8_t keyCtrl; // Keyboard state flag control.
|
||||
bool optionSelect; // Flag to indicate a user requested keyboard configuration option is being selected.
|
||||
int uartNum;
|
||||
int uartBufferSize;
|
||||
int uartQueueSize;
|
||||
|
||||
std::string fsPath; // Path on the underlying filesystem where storage is mounted and accessible.
|
||||
t_keyMapEntry *kme; // Pointer to an array in memory to contain PS2 to NEC PC-9801 mapping values.
|
||||
int kmeRows; // Number of rows in the kme table.
|
||||
std::string keyMapFileName; // Name of file where extension or replacement key map entries are stored.
|
||||
bool persistConfig; // Flag to request saving of the config into NVS storage.
|
||||
} t_pcControl;
|
||||
|
||||
// Transmit buffer queue item.
|
||||
typedef struct {
|
||||
uint32_t keyCode; // Key data to be sent to PC-9801, 4 bytes to allow for extended sequences..
|
||||
} t_xmitQueueMessage;
|
||||
|
||||
// Receive buffer queue item.
|
||||
typedef struct {
|
||||
uint8_t hostCmd; // Keyboard configuration command received from X68000.
|
||||
} t_rcvQueueMessage;
|
||||
|
||||
// Thread handles - one per function, ie. HID interface and host target interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Control structure to control interaction and mapping of keys for the host.
|
||||
t_pcControl pcCtrl;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE pcMutex;
|
||||
|
||||
//
|
||||
// This mapping is for the UK Wyse KB-3926 PS/2 keyboard
|
||||
//
|
||||
t_keyMap PS2toPC9801 = {
|
||||
{
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine PC-9801 Data PC-9801 Ctrl (Flags to Set).
|
||||
// Function keys
|
||||
// { PS2_KEY_F1, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_HIRAGANA, PC9801_CTRL_NONE, }, // CTRL + F1 = Hiragana
|
||||
// { PS2_KEY_F2, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_FULLWIDTH, PC9801_CTRL_NONE, }, // CTRL + F2 = Full Width
|
||||
// { PS2_KEY_F3, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KATAKANA, PC9801_CTRL_NONE, }, // CTRL + F3 = Katakana
|
||||
// { PS2_KEY_F4, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_ROMAJI, PC9801_CTRL_NONE, }, // CTRL + F4 = Romaji
|
||||
// { PS2_KEY_F5, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_TRANSPOSE, PC9801_CTRL_NONE, }, // CTRL + F5 = Tranpose
|
||||
// { PS2_KEY_F6, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SYMBOL, PC9801_CTRL_NONE, }, // CTRL + F6 = Symbol
|
||||
// { PS2_KEY_F7, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_REGISTRATION, PC9801_CTRL_NONE, }, // CTRL + F7 = Registration - maybe a poor translation, needs better one!
|
||||
// { PS2_KEY_F9, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_COPY, PC9801_CTRL_NONE, }, // CTRL + F9 = Copy
|
||||
// { PS2_KEY_F10, PS2CTRL_FUNC | PS2CTRL_CTRL, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_HELP, PC9801_CTRL_NONE, }, // CTRL + F10 = Help
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F1, PC9801_CTRL_NONE, }, // F1
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F2, PC9801_CTRL_NONE, }, // F2
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F3, PC9801_CTRL_NONE, }, // F3
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F4, PC9801_CTRL_NONE, }, // F4
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F5, PC9801_CTRL_NONE, }, // F5
|
||||
{ PS2_KEY_F6, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F6, PC9801_CTRL_NONE, }, // F6
|
||||
{ PS2_KEY_F7, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F7, PC9801_CTRL_NONE, }, // F7
|
||||
{ PS2_KEY_F8, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F8, PC9801_CTRL_NONE, }, // F8
|
||||
{ PS2_KEY_F9, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F9, PC9801_CTRL_NONE, }, // F9
|
||||
{ PS2_KEY_F10, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F10, PC9801_CTRL_NONE, }, // F10
|
||||
// { PS2_KEY_F11, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_OPT_1, PC9801_CTRL_NONE, }, // F11 - OPT.1
|
||||
// { PS2_KEY_F12, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_OPT_2, PC9801_CTRL_NONE, }, // F12 - OPT.2
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine PC-9801 Data PC-9801 Ctrl (Flags to Set).
|
||||
// ALPHA keys, case is maaped in the PC-9801 via the SHIFT key event or CAPS key.
|
||||
{ PS2_KEY_A, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_A, PC9801_CTRL_NONE, }, // A
|
||||
{ PS2_KEY_B, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_B, PC9801_CTRL_NONE, }, // B
|
||||
{ PS2_KEY_C, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_C, PC9801_CTRL_NONE, }, // C
|
||||
{ PS2_KEY_D, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_D, PC9801_CTRL_NONE, }, // D
|
||||
{ PS2_KEY_E, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_E, PC9801_CTRL_NONE, }, // E
|
||||
{ PS2_KEY_F, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_F, PC9801_CTRL_NONE, }, // F
|
||||
{ PS2_KEY_G, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_G, PC9801_CTRL_NONE, }, // G
|
||||
{ PS2_KEY_H, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_H, PC9801_CTRL_NONE, }, // H
|
||||
{ PS2_KEY_I, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_I, PC9801_CTRL_NONE, }, // I
|
||||
{ PS2_KEY_J, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_J, PC9801_CTRL_NONE, }, // J
|
||||
{ PS2_KEY_K, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_K, PC9801_CTRL_NONE, }, // K
|
||||
{ PS2_KEY_L, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_L, PC9801_CTRL_NONE, }, // L
|
||||
{ PS2_KEY_M, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_M, PC9801_CTRL_NONE, }, // M
|
||||
{ PS2_KEY_N, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_N, PC9801_CTRL_NONE, }, // N
|
||||
{ PS2_KEY_O, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_O, PC9801_CTRL_NONE, }, // O
|
||||
{ PS2_KEY_P, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_P, PC9801_CTRL_NONE, }, // P
|
||||
{ PS2_KEY_Q, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_Q, PC9801_CTRL_NONE, }, // Q
|
||||
{ PS2_KEY_R, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_R, PC9801_CTRL_NONE, }, // R
|
||||
{ PS2_KEY_S, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_S, PC9801_CTRL_NONE, }, // S
|
||||
{ PS2_KEY_T, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_T, PC9801_CTRL_NONE, }, // T
|
||||
{ PS2_KEY_U, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_U, PC9801_CTRL_NONE, }, // U
|
||||
{ PS2_KEY_V, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_V, PC9801_CTRL_NONE, }, // V
|
||||
{ PS2_KEY_W, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_W, PC9801_CTRL_NONE, }, // W
|
||||
{ PS2_KEY_X, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_X, PC9801_CTRL_NONE, }, // X
|
||||
{ PS2_KEY_Y, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_Y, PC9801_CTRL_NONE, }, // Y
|
||||
{ PS2_KEY_Z, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_Z, PC9801_CTRL_NONE, }, // Z
|
||||
// Numeric keys.
|
||||
{ PS2_KEY_0, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_9, PC9801_CTRL_NONE, }, // Close Bracket )
|
||||
{ PS2_KEY_0, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_0, PC9801_CTRL_NONE, }, // 0
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_1, PC9801_CTRL_NONE, }, // 1
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_2, PC9801_CTRL_NONE, }, // 2
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_3, PC9801_CTRL_NONE, }, // 3
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_4, PC9801_CTRL_NONE, }, // 4
|
||||
{ PS2_KEY_5, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_5, PC9801_CTRL_NONE, }, // 5
|
||||
{ PS2_KEY_6, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CIRCUMFLEX, PC9801_CTRL_RELEASESHIFT, }, // Circumflex ^
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_6, PC9801_CTRL_NONE, }, // 6
|
||||
{ PS2_KEY_7, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_6, PC9801_CTRL_NONE, }, // &
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_7, PC9801_CTRL_NONE, }, // 7
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_COLON, PC9801_CTRL_NONE, }, // Start *
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_8, PC9801_CTRL_NONE, }, // 8
|
||||
{ PS2_KEY_9, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_8, PC9801_CTRL_NONE, }, // Open Bracket (
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_9, PC9801_CTRL_NONE, }, // 9
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine PC-9801 Data PC-9801 Ctrl (Flags to Set).
|
||||
// Punctuation keys.
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SPACE, PC9801_CTRL_NONE, }, // Space
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CIRCUMFLEX, PC9801_CTRL_NONE, }, // Upper Bar
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_MINUS, PC9801_CTRL_NONE, }, // Minus -
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SEMI, PC9801_CTRL_SHIFT, }, // Plus +
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_MINUS, PC9801_CTRL_SHIFT, }, // Equal =
|
||||
{ PS2_KEY_DOT, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_DOT, PC9801_CTRL_NONE, }, // Greater Than >
|
||||
{ PS2_KEY_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_DOT, PC9801_CTRL_NONE, }, // Dot
|
||||
{ PS2_KEY_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_DIV, PC9801_CTRL_NONE, }, // Divide /
|
||||
{ PS2_KEY_SEMI, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_COLON, PC9801_CTRL_RELEASESHIFT, }, // Colon :
|
||||
{ PS2_KEY_SEMI, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SEMI, PC9801_CTRL_NONE, }, // Semi-Colon ;
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_OPEN_SQ, PC9801_CTRL_NONE, }, // [
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CLOSE_SQ, PC9801_CTRL_NONE, }, // ]
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_AT, PC9801_CTRL_RELEASESHIFT, }, // @
|
||||
{ PS2_KEY_APOS, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_7, PC9801_CTRL_SHIFT, }, // '
|
||||
{ PS2_KEY_BACK, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_YEN, PC9801_CTRL_NONE, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_BACK, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_YEN, PC9801_CTRL_NONE, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_HASH, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_3, PC9801_CTRL_SHIFT, }, // Hash
|
||||
{ PS2_KEY_COMMA, PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_COMMA, PC9801_CTRL_NONE, }, // Less Than <
|
||||
{ PS2_KEY_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_COMMA, PC9801_CTRL_NONE, }, // Comma ,
|
||||
{ PS2_KEY_BTICK, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_UNDERLINE, PC9801_CTRL_SHIFT, }, // Underline
|
||||
{ PS2_KEY_BTICK, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_AT, PC9801_CTRL_SHIFT, }, // Back Tick `
|
||||
// Control keys.
|
||||
{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_TAB, PC9801_CTRL_NONE, }, // TAB
|
||||
{ PS2_KEY_BS, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_BS, PC9801_CTRL_NONE, }, // Backspace
|
||||
{ PS2_KEY_ESC, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_ESC, PC9801_CTRL_NONE, }, // ESCape
|
||||
{ PS2_KEY_INSERT, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_INS, PC9801_CTRL_NONE, }, // INSERT
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CLR, PC9801_CTRL_NONE, }, // CLR
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_HOME, PC9801_CTRL_NONE, }, // HOME
|
||||
{ PS2_KEY_DELETE, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_DEL, PC9801_CTRL_NONE, }, // DELETE
|
||||
{ PS2_KEY_UP_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_UP_ARROW, PC9801_CTRL_NONE, }, // Up Arrow
|
||||
{ PS2_KEY_L_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_L_ARROW, PC9801_CTRL_NONE, }, // Left Arrow
|
||||
{ PS2_KEY_DN_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_DN_ARROW, PC9801_CTRL_NONE, }, // Down Arrow
|
||||
{ PS2_KEY_R_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_R_ARROW, PC9801_CTRL_NONE, }, // Right Arrow
|
||||
{ PS2_KEY_PGUP, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_ROLLUP, PC9801_CTRL_NONE, }, // Roll Up.
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_ROLLDN, PC9801_CTRL_NONE, }, // Roll Down
|
||||
{ PS2_KEY_SCROLL, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, ' ', PC9801_CTRL_NONE, }, // Not assigned.
|
||||
{ PS2_KEY_ENTER, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_RETURN, PC9801_CTRL_NONE, }, // Not assigned.
|
||||
{ PS2_KEY_CAPS, PS2CTRL_CAPS, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CAPS, PC9801_CTRL_NONE, }, // CAPS
|
||||
{ PS2_KEY_END, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_UNDO, PC9801_CTRL_NONE, }, // UNDO
|
||||
// Keypad.
|
||||
{ PS2_KEY_KP0, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP0, PC9801_CTRL_NONE, }, // Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP1, PC9801_CTRL_NONE, }, // Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP2, PC9801_CTRL_NONE, }, // Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP3, PC9801_CTRL_NONE, }, // Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP4, PC9801_CTRL_NONE, }, // Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP5, PC9801_CTRL_NONE, }, // Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP6, PC9801_CTRL_NONE, }, // Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP7, PC9801_CTRL_NONE, }, // Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP8, PC9801_CTRL_NONE, }, // Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP9, PC9801_CTRL_NONE, }, // Keypad 9
|
||||
{ PS2_KEY_KP_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_COMMA, PC9801_CTRL_NONE, }, // Keypad Comma ,
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_DOT, PC9801_CTRL_NONE, }, // Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_PLUS, PC9801_CTRL_NONE, }, // Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_MINUS, PC9801_CTRL_NONE, }, // Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_TIMES, PC9801_CTRL_NONE, }, // Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_DIV, PC9801_CTRL_NONE, }, // Keypad Divide /
|
||||
{ PS2_KEY_KP_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_MINUS, PC9801_CTRL_SHIFT, }, // Keypad Equal =
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_ENTER, PC9801_CTRL_NONE, }, // Keypad Ebter /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_KP_EQUAL, PC9801_CTRL_NONE, }, // Keypad Ebter /
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine PC-9801 Data PC-9801 Ctrl (Flags to Set).
|
||||
// Special keys.
|
||||
{ PS2_KEY_PRTSCR, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, 0x00, PC9801_CTRL_NONE, }, //
|
||||
{ PS2_KEY_PAUSE, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_BREAK, PC9801_CTRL_RELEASESHIFT, }, // BREAK KEY
|
||||
// { PS2_KEY_L_GUI, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_XF1, PC9801_CTRL_NONE, }, // XF1
|
||||
// { PS2_KEY_L_ALT, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_XF2, PC9801_CTRL_NONE, }, // XF2
|
||||
// { PS2_KEY_R_ALT, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_XF3, PC9801_CTRL_NONE, }, // XF3
|
||||
// { PS2_KEY_R_GUI, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_XF4, PC9801_CTRL_NONE, }, // XF4
|
||||
// { PS2_KEY_MENU, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_XF5, PC9801_CTRL_NONE, }, // XF5
|
||||
// Modifiers are last, only being selected if an earlier match isnt made.
|
||||
{ PS2_KEY_L_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SHIFT, PC9801_CTRL_NONE, }, //
|
||||
{ PS2_KEY_R_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_SHIFT, PC9801_CTRL_NONE, }, //
|
||||
{ PS2_KEY_L_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CTRL, PC9801_CTRL_NONE, }, // Map to Control
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_CTRL, PC9801_CTRL_NONE, }, // Map to Control
|
||||
{ 0, PS2CTRL_NONE, KEYMAP_STANDARD, PC9801_ALL, PC9801_KEY_NULL, PC9801_CTRL_NONE, }, //
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // PC9801_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/PS2KeyAdvanced.h
|
||||
451
main/include/PS2KeyAdvanced.h
Normal file
451
main/include/PS2KeyAdvanced.h
Normal file
@@ -0,0 +1,451 @@
|
||||
/* Version V1.0.9
|
||||
PS2KeyAdvanced.h - PS2KeyAdvanced library
|
||||
Copyright (c) 2007 Free Software Foundation. All right reserved.
|
||||
Written by Paul Carpenter, PC Services <sales@pcserviceselectronics.co.uk>
|
||||
Created September 2014
|
||||
Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management
|
||||
January 2020 Fix typos, correct keyboard reset status improve library.properties
|
||||
and additional platform handling and some documentation
|
||||
March 2020 Add SAMD1 as recognised support as has been tested by user
|
||||
Improve different architecture handling
|
||||
November 2020 Add support for STM32 from user Hiabuto-de
|
||||
Tested on STM32Duino-Framework and PlatformIO on STM32F103C8T6 and an IBM Model M
|
||||
July 2021 Add workaround for ESP32 issue with Silicon (hardware) from user submissions
|
||||
|
||||
IMPORTANT WARNING
|
||||
|
||||
If using a DUE or similar board with 3V3 I/O you MUST put a level translator
|
||||
like a Texas Instruments TXS0102 or FET circuit as the signals are
|
||||
Bi-directional (signals transmitted from both ends on same wire).
|
||||
|
||||
Failure to do so may damage your Arduino Due or similar board.
|
||||
|
||||
Test History
|
||||
September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0
|
||||
January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board
|
||||
Manager V1.6.6
|
||||
|
||||
ONLY use defines in this file others may disappear on updates.
|
||||
|
||||
This is for a LATIN style keyboard using Scan code set 2. See various
|
||||
websites on what different scan code sets use. Scan Code Set 2 is the
|
||||
default scan code set for PS2 keyboards on power up.
|
||||
|
||||
Will support most keyboards even ones with multimedia keys or even 24 function keys.
|
||||
|
||||
Fully featured PS2 keyboard library to provide
|
||||
All function and movement keys supported even multi-lingual
|
||||
Parity checking of data sent/received on receive request keyboard resend
|
||||
Resends data when needed handles keyboard protocol for RESEND and ECHO
|
||||
Functions for get and set of
|
||||
Scancode set in use READ only
|
||||
LED and LOCK control
|
||||
ReadID
|
||||
Reset keyboard
|
||||
Send ECHO
|
||||
Ignore Break codes for keys
|
||||
Ignore typematic repeat of CTRL, SHIFT, ALT, Num, Scroll, Caps
|
||||
Handles NUM, CAPS and SCROLL lock keys to LEDs
|
||||
Handles NUM/SCROLL internally
|
||||
|
||||
Read function Returns an UNSIGNED INT containing
|
||||
Make/Break status
|
||||
Caps status
|
||||
Shift, CTRL, ALT, ALT GR, GUI keys
|
||||
Flag for function key not a displayable/printable character
|
||||
8 bit key code
|
||||
|
||||
Code Ranges (bottom byte of unsigned int)
|
||||
0 invalid/error
|
||||
1-1F Functions (Caps, Shift, ALT, Enter, DEL... )
|
||||
1A-1F Functions with ASCII control code
|
||||
(DEL, BS, TAB, ESC, ENTER, SPACE)
|
||||
20-61 Printable characters noting
|
||||
0-9 = 0x30 to 0x39 as ASCII
|
||||
A to Z = 0x41 to 0x5A as upper case ASCII type codes
|
||||
8B Extra European key
|
||||
61-A0 Function keys and other special keys (plus F2 and F1)
|
||||
61-78 F1 to F24
|
||||
79-8A Multimedia
|
||||
8B NOT included
|
||||
8C-8E ACPI power
|
||||
91-A0 and F2 and F1 - Special multilingual
|
||||
A8-FF Keyboard communications commands (note F2 and F1 are special
|
||||
codes for special multi-lingual keyboards)
|
||||
|
||||
By using these ranges it is possible to perform detection of any key and do
|
||||
easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code.
|
||||
|
||||
Top Byte is 8 bits denoting as follows with defines for bit code
|
||||
|
||||
Define name bit description
|
||||
PS2_BREAK 15 1 = Break key code
|
||||
(MSB) 0 = Make Key code
|
||||
PS2_SHIFT 14 1 = Shift key pressed as well (either side)
|
||||
0 = NO shift key
|
||||
PS2_CTRL 13 1 = Ctrl key pressed as well (either side)
|
||||
0 = NO Ctrl key
|
||||
PS2_CAPS 12 1 = Caps Lock ON
|
||||
0 = Caps lock OFF
|
||||
PS2_ALT 11 1 = Left Alt key pressed as well
|
||||
0 = NO Left Alt key
|
||||
PS2_ALT_GR 10 1 = Right Alt (Alt GR) key pressed as well
|
||||
0 = NO Right Alt key
|
||||
PS2_GUI 9 1 = GUI key pressed as well (either)
|
||||
0 = NO GUI key
|
||||
PS2_FUNCTION 8 1 = FUNCTION key non-printable character (plus space, tab, enter)
|
||||
0 = standard character key
|
||||
|
||||
Error Codes
|
||||
Most functions return 0 or 0xFFFF as error, other codes to note and
|
||||
handle appropriately
|
||||
0xAA keyboard has reset and passed power up tests
|
||||
will happen if keyboard plugged in after code start
|
||||
0xFC Keyboard General error or power up fail
|
||||
|
||||
It is responsibility of your programme to deal with converting special cases like
|
||||
<CTRL>+<ENTER> sends a special code to something else. If you wish to do that make a
|
||||
NEW library called SOMETHING different NOT a variant or revision of this one, as you
|
||||
are changing base functionality
|
||||
|
||||
See PS2KeyCode.h for codes from the keyboard this library uses to decode.
|
||||
(may disappear in updates do not rely on that file or definitions)
|
||||
|
||||
See this file for returned definitions of Keys
|
||||
|
||||
Note defines starting
|
||||
PS2_KC_* are internal defines for codes from the keyboard
|
||||
PS2_KEY_* are the codes this library returns
|
||||
PS2_* remaining defines for use in higher levels
|
||||
|
||||
To get the key as ASCII/UTF-8 single byte character conversion requires use
|
||||
of PS2KeyMap library AS WELL.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef PS2KeyAdvanced_h
|
||||
#define PS2KeyAdvanced_h
|
||||
|
||||
// Platform specific areas
|
||||
// Harvard architecture settings for PROGMEM
|
||||
// Add separate for EACH architecture as easier to maintain
|
||||
// AVR (includes Teensy 2.0)
|
||||
#if defined( ARDUINO_ARCH_AVR )
|
||||
#define PS2_SUPPORTED 1
|
||||
#define PS2_REQUIRES_PROGMEM 1
|
||||
#define PS2_CLEAR_PENDING_IRQ 1
|
||||
#endif
|
||||
// SAM (Due)
|
||||
#if defined( ARDUINO_ARCH_SAM )
|
||||
#define PS2_SUPPORTED 1
|
||||
#define PS2_CLEAR_PENDING_IRQ 1
|
||||
#endif
|
||||
// SAMD1
|
||||
#if defined( ARDUINO_ARCH_SAMD1 )
|
||||
#define PS2_SUPPORTED 1
|
||||
#define PS2_CLEAR_PENDING_IRQ 1
|
||||
#endif
|
||||
// STM32
|
||||
#if defined( ARDUINO_ARCH_STM32 )
|
||||
#define PS2_SUPPORTED 1
|
||||
#define PS2_CLEAR_PENDING_IRQ 1
|
||||
#endif
|
||||
// ESP32
|
||||
#if defined( ARDUINO_ARCH_ESP32 )
|
||||
#define PS2_SUPPORTED 1
|
||||
#define PS2_ONLY_CHANGE_IRQ 1
|
||||
#endif
|
||||
|
||||
// Invalid architecture
|
||||
#if !( defined( PS2_SUPPORTED ) )
|
||||
#warning Library is NOT supported on this board Use at your OWN risk
|
||||
#endif
|
||||
|
||||
/* Flags/bit masks for status bits in returned unsigned int value */
|
||||
#define PS2_BREAK 0x8000
|
||||
#define PS2_SHIFT 0x4000
|
||||
#define PS2_CTRL 0x2000
|
||||
#define PS2_CAPS 0x1000
|
||||
#define PS2_ALT 0x800
|
||||
#define PS2_ALT_GR 0x400
|
||||
#define PS2_GUI 0x200
|
||||
#define PS2_FUNCTION 0x100
|
||||
|
||||
/* General defines of communications codes */
|
||||
/* Command or response */
|
||||
#define PS2_KEY_RESEND 0xFE
|
||||
#define PS2_KEY_ACK 0xFA
|
||||
#define PS2_KEY_ECHO 0xEE
|
||||
/* Responses */
|
||||
#define PS2_KEY_BAT 0xAA
|
||||
// Actually buffer overrun
|
||||
#define PS2_KEY_OVERRUN 0xFF
|
||||
// Below is general error code
|
||||
#define PS2_KEY_ERROR 0xFC
|
||||
|
||||
/* Command parameters for functions */
|
||||
/* LED codes OR together */
|
||||
#define PS2_LOCK_SCROLL 0x01
|
||||
#define PS2_LOCK_NUM 0x02
|
||||
#define PS2_LOCK_CAPS 0x04
|
||||
/* Only useful for very few keyboards */
|
||||
#define PS2_LOCK_EXTRA 0x08
|
||||
|
||||
/* Returned keycode definitions */
|
||||
/* Do NOT change these codings as you will break base
|
||||
functionality use PS2KeyMap for that and internationalisation */
|
||||
#define PS2_KEY_NUM 0x01
|
||||
#define PS2_KEY_SCROLL 0x02
|
||||
#define PS2_KEY_CAPS 0x03
|
||||
#define PS2_KEY_PRTSCR 0x04
|
||||
#define PS2_KEY_PAUSE 0x05
|
||||
#define PS2_KEY_L_SHIFT 0x06
|
||||
#define PS2_KEY_R_SHIFT 0x07
|
||||
#define PS2_KEY_L_CTRL 0X08
|
||||
#define PS2_KEY_R_CTRL 0X09
|
||||
#define PS2_KEY_L_ALT 0x0A
|
||||
#define PS2_KEY_R_ALT 0x0B
|
||||
/* Sometimes called windows key */
|
||||
#define PS2_KEY_L_GUI 0x0C
|
||||
#define PS2_KEY_R_GUI 0x0D
|
||||
#define PS2_KEY_MENU 0x0E
|
||||
/* Break is CTRL + PAUSE generated inside keyboard */
|
||||
#define PS2_KEY_BREAK 0x0F
|
||||
/* Generated by some keyboards by ALT and PRTSCR */
|
||||
#define PS2_KEY_SYSRQ 0x10
|
||||
#define PS2_KEY_HOME 0x11
|
||||
#define PS2_KEY_END 0x12
|
||||
#define PS2_KEY_PGUP 0x13
|
||||
#define PS2_KEY_PGDN 0x14
|
||||
#define PS2_KEY_L_ARROW 0x15
|
||||
#define PS2_KEY_R_ARROW 0x16
|
||||
#define PS2_KEY_UP_ARROW 0x17
|
||||
#define PS2_KEY_DN_ARROW 0x18
|
||||
#define PS2_KEY_INSERT 0x19
|
||||
#define PS2_KEY_DELETE 0x1A
|
||||
#define PS2_KEY_ESC 0x1B
|
||||
#define PS2_KEY_BS 0x1C
|
||||
#define PS2_KEY_TAB 0x1D
|
||||
#define PS2_KEY_ENTER 0x1E
|
||||
#define PS2_KEY_SPACE 0x1F
|
||||
#define PS2_KEY_KP0 0x20
|
||||
#define PS2_KEY_KP1 0x21
|
||||
#define PS2_KEY_KP2 0x22
|
||||
#define PS2_KEY_KP3 0x23
|
||||
#define PS2_KEY_KP4 0x24
|
||||
#define PS2_KEY_KP5 0x25
|
||||
#define PS2_KEY_KP6 0x26
|
||||
#define PS2_KEY_KP7 0x27
|
||||
#define PS2_KEY_KP8 0x28
|
||||
#define PS2_KEY_KP9 0x29
|
||||
#define PS2_KEY_KP_DOT 0x2A
|
||||
#define PS2_KEY_KP_ENTER 0x2B
|
||||
#define PS2_KEY_KP_PLUS 0x2C
|
||||
#define PS2_KEY_KP_MINUS 0x2D
|
||||
#define PS2_KEY_KP_TIMES 0x2E
|
||||
#define PS2_KEY_KP_DIV 0x2F
|
||||
#define PS2_KEY_0 0X30
|
||||
#define PS2_KEY_1 0X31
|
||||
#define PS2_KEY_2 0X32
|
||||
#define PS2_KEY_3 0X33
|
||||
#define PS2_KEY_4 0X34
|
||||
#define PS2_KEY_5 0X35
|
||||
#define PS2_KEY_6 0X36
|
||||
#define PS2_KEY_7 0X37
|
||||
#define PS2_KEY_8 0X38
|
||||
#define PS2_KEY_9 0X39
|
||||
#define PS2_KEY_APOS 0X3A
|
||||
#define PS2_KEY_COMMA 0X3B
|
||||
#define PS2_KEY_MINUS 0X3C
|
||||
#define PS2_KEY_DOT 0X3D
|
||||
#define PS2_KEY_DIV 0X3E
|
||||
/* Some Numeric keyboards have an '=' on right keypad */
|
||||
#define PS2_KEY_KP_EQUAL 0x3F
|
||||
/* Single quote or back quote */
|
||||
#define PS2_KEY_SINGLE 0X40
|
||||
#define PS2_KEY_A 0X41
|
||||
#define PS2_KEY_B 0X42
|
||||
#define PS2_KEY_C 0X43
|
||||
#define PS2_KEY_D 0X44
|
||||
#define PS2_KEY_E 0X45
|
||||
#define PS2_KEY_F 0X46
|
||||
#define PS2_KEY_G 0X47
|
||||
#define PS2_KEY_H 0X48
|
||||
#define PS2_KEY_I 0X49
|
||||
#define PS2_KEY_J 0X4A
|
||||
#define PS2_KEY_K 0X4B
|
||||
#define PS2_KEY_L 0X4C
|
||||
#define PS2_KEY_M 0X4D
|
||||
#define PS2_KEY_N 0X4E
|
||||
#define PS2_KEY_O 0X4F
|
||||
#define PS2_KEY_P 0X50
|
||||
#define PS2_KEY_Q 0X51
|
||||
#define PS2_KEY_R 0X52
|
||||
#define PS2_KEY_S 0X53
|
||||
#define PS2_KEY_T 0X54
|
||||
#define PS2_KEY_U 0X55
|
||||
#define PS2_KEY_V 0X56
|
||||
#define PS2_KEY_W 0X57
|
||||
#define PS2_KEY_X 0X58
|
||||
#define PS2_KEY_Y 0X59
|
||||
#define PS2_KEY_Z 0X5A
|
||||
#define PS2_KEY_SEMI 0X5B
|
||||
#define PS2_KEY_BACK 0X5C
|
||||
#define PS2_KEY_OPEN_SQ 0X5D
|
||||
#define PS2_KEY_CLOSE_SQ 0X5E
|
||||
#define PS2_KEY_EQUAL 0X5F
|
||||
/* Some Numeric keypads have a comma key */
|
||||
#define PS2_KEY_KP_COMMA 0x60
|
||||
#define PS2_KEY_F1 0X61
|
||||
#define PS2_KEY_F2 0X62
|
||||
#define PS2_KEY_F3 0X63
|
||||
#define PS2_KEY_F4 0X64
|
||||
#define PS2_KEY_F5 0X65
|
||||
#define PS2_KEY_F6 0X66
|
||||
#define PS2_KEY_F7 0X67
|
||||
#define PS2_KEY_F8 0X68
|
||||
#define PS2_KEY_F9 0X69
|
||||
#define PS2_KEY_F10 0X6A
|
||||
#define PS2_KEY_F11 0X6B
|
||||
#define PS2_KEY_F12 0X6C
|
||||
#define PS2_KEY_F13 0X6D
|
||||
#define PS2_KEY_F14 0X6E
|
||||
#define PS2_KEY_F15 0X6F
|
||||
#define PS2_KEY_F16 0X70
|
||||
#define PS2_KEY_F17 0X71
|
||||
#define PS2_KEY_F18 0X72
|
||||
#define PS2_KEY_F19 0X73
|
||||
#define PS2_KEY_F20 0X74
|
||||
#define PS2_KEY_F21 0X75
|
||||
#define PS2_KEY_F22 0X76
|
||||
#define PS2_KEY_F23 0X77
|
||||
#define PS2_KEY_F24 0X78
|
||||
#define PS2_KEY_NEXT_TR 0X79
|
||||
#define PS2_KEY_PREV_TR 0X7A
|
||||
#define PS2_KEY_STOP 0X7B
|
||||
#define PS2_KEY_PLAY 0X7C
|
||||
#define PS2_KEY_MUTE 0X7D
|
||||
#define PS2_KEY_VOL_UP 0X7E
|
||||
#define PS2_KEY_VOL_DN 0X7F
|
||||
#define PS2_KEY_MEDIA 0X80
|
||||
#define PS2_KEY_EMAIL 0X81
|
||||
#define PS2_KEY_CALC 0X82
|
||||
#define PS2_KEY_COMPUTER 0X83
|
||||
#define PS2_KEY_WEB_SEARCH 0X84
|
||||
#define PS2_KEY_WEB_HOME 0X85
|
||||
#define PS2_KEY_WEB_BACK 0X86
|
||||
#define PS2_KEY_WEB_FORWARD 0X87
|
||||
#define PS2_KEY_WEB_STOP 0X88
|
||||
#define PS2_KEY_WEB_REFRESH 0X89
|
||||
#define PS2_KEY_WEB_FAVOR 0X8A
|
||||
#define PS2_KEY_EUROPE2 0X8B
|
||||
#define PS2_KEY_POWER 0X8C
|
||||
#define PS2_KEY_SLEEP 0X8D
|
||||
#define PS2_KEY_WAKE 0X90
|
||||
#define PS2_KEY_INTL1 0X91
|
||||
#define PS2_KEY_INTL2 0X92
|
||||
#define PS2_KEY_INTL3 0X93
|
||||
#define PS2_KEY_INTL4 0X94
|
||||
#define PS2_KEY_INTL5 0X95
|
||||
#define PS2_KEY_LANG1 0X96
|
||||
#define PS2_KEY_LANG2 0X97
|
||||
#define PS2_KEY_LANG3 0X98
|
||||
#define PS2_KEY_LANG4 0X99
|
||||
#define PS2_KEY_LANG5 0xA0
|
||||
#define PS2_KEY_BTICK 0X9A
|
||||
#define PS2_KEY_HASH 0X9B
|
||||
|
||||
/*
|
||||
Purpose: Provides advanced access to PS2 keyboards
|
||||
Public class definitions
|
||||
|
||||
See standard error codes for error code returns
|
||||
*/
|
||||
class PS2KeyAdvanced {
|
||||
public:
|
||||
/* This constructor does basically nothing. Please call the begin(int,int)
|
||||
method before using any other method of this class. */
|
||||
PS2KeyAdvanced( );
|
||||
|
||||
// Destructor - disable and detach interrupts and free up resources.
|
||||
~PS2KeyAdvanced( );
|
||||
|
||||
/* Starts the keyboard "service" by registering the external interrupt.
|
||||
setting the pin modes correctly and driving those needed to high.
|
||||
Sets default LOCK status (LEDs) to passed in value or default of all off
|
||||
The best place to call this method is in the setup routine. */
|
||||
void begin( uint8_t, uint8_t );
|
||||
|
||||
// Additional key available check which doesnt affect the queue.
|
||||
uint8_t keyAvailable(void);
|
||||
|
||||
/* Returns number of codes available or 0 for none */
|
||||
uint8_t available( );
|
||||
|
||||
/* Returns the key last read from the keyboard.
|
||||
If there is no key available, 0 is returned. */
|
||||
uint16_t read( );
|
||||
|
||||
/* Returns the current status of Locks
|
||||
Use Macro to mask out bits from
|
||||
PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */
|
||||
uint8_t getLock( );
|
||||
|
||||
/* Sets the current status of Locks and LEDs
|
||||
Use macro defines added together from
|
||||
PS2_LOCK_NUM PS2_LOCK_CAPS PS2_LOCK_SCROLL */
|
||||
void setLock( uint8_t );
|
||||
|
||||
/* Set library to not send break key codes
|
||||
1 = no break codes
|
||||
0 = send break codes */
|
||||
void setNoBreak( uint8_t );
|
||||
|
||||
/* Set library to not repeat make codes for CTRL, ALT, GUI, SHIFT
|
||||
1 = no repeat codes
|
||||
0 = send repeat codes */
|
||||
void setNoRepeat( uint8_t );
|
||||
|
||||
/* Resets keyboard when reset has completed
|
||||
keyboard sends AA - Pass or FC for fail
|
||||
Read from keyboard data buffer */
|
||||
void resetKey( );
|
||||
|
||||
/* Get the current Scancode Set used in keyboard
|
||||
returned data in keyboard buffer read as keys */
|
||||
void getScanCodeSet( void );
|
||||
|
||||
/* Get the current Scancode Set used in keyboard
|
||||
returned data in keyboard buffer read as keys */
|
||||
void readID( void );
|
||||
|
||||
/* Send Echo command to keyboard
|
||||
returned data in keyboard buffer read as keys */
|
||||
void echo( void );
|
||||
|
||||
// Method to suspend PS2 activity, primarily by disabling the interrupts.
|
||||
void suspend(bool suspend);
|
||||
|
||||
/* Send Typematic rate/delay command to keyboard
|
||||
First Parameter rate is 0 - 0x1F (31)
|
||||
0 = 30 CPS
|
||||
0x1F = 2 CPS
|
||||
default in keyboard is 0xB (10.9 CPS)
|
||||
Second Parameter delay is 0 - 3 for 0.25s to 1s in 0.25 increments
|
||||
default in keyboard is 1 = 0.5 second delay
|
||||
Returned data in keyboard buffer read as keys */
|
||||
int typematic( uint8_t , uint8_t );
|
||||
};
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/PS2KeyCode.h
|
||||
276
main/include/PS2KeyCode.h
Normal file
276
main/include/PS2KeyCode.h
Normal file
@@ -0,0 +1,276 @@
|
||||
/* Version V1.0.8
|
||||
PS2KeyCode.h - PS2KeyAdvanced library Internal actual PS2 key code sequences
|
||||
Copyright (c) 2007 Free Software Foundation. All right reserved.
|
||||
Written by Paul Carpenter, PC Services <sales@pcserviceselectronics.co.uk>
|
||||
Created September 2014
|
||||
Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management
|
||||
Updated December 2019 - Paul Carpenter - Fix typo in code for Multimedia STOP
|
||||
|
||||
PRIVATE to library
|
||||
|
||||
Test History
|
||||
September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0
|
||||
January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board
|
||||
Manager V1.6.6
|
||||
|
||||
This is for a LATIN style keyboard. Will support most keyboards even ones
|
||||
with multimedia keys or even 24 function keys.
|
||||
|
||||
Definitions used for key codes from a PS2 keyboard, do not use in your
|
||||
code these are to be handled INTERNALLY by the library.
|
||||
(may disappear in updates do not rely on this file or definitions)
|
||||
|
||||
See PS2KeyAdvanced.h for codes returned from library and flag settings
|
||||
|
||||
Defines are in three groups
|
||||
|
||||
Special codes definition of communications bytes
|
||||
|
||||
Single Byte codes returned as key codes
|
||||
|
||||
Two byte Codes preceded by E0 code returned as keycodes
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef PS2KeyCode_h
|
||||
#define PS2KeyCode_h
|
||||
|
||||
/* Ignore code for key code translation */
|
||||
#define PS2_KEY_IGNORE 0xBB
|
||||
|
||||
// buffer sizes keyboard RX and TX, then key reading buffer
|
||||
// Minimum size 8 can be larger
|
||||
#define _RX_BUFFER_SIZE 8
|
||||
// Minimum size 6 can be larger
|
||||
#define _TX_BUFFER_SIZE 6
|
||||
// Output Buffer of unsigned int values. Minimum size 4 can be larger
|
||||
#define _KEY_BUFF_SIZE 4
|
||||
|
||||
/* private defines for library files not global */
|
||||
/* _ps2mode status flags */
|
||||
#define _PS2_BUSY 0x80
|
||||
#define _TX_MODE 0x40
|
||||
#define _BREAK_KEY 0x20
|
||||
#define _WAIT_RESPONSE 0x10
|
||||
#define _E0_MODE 0x08
|
||||
#define _E1_MODE 0x04
|
||||
#define _LAST_VALID 0x02
|
||||
|
||||
/* _tx_ready flags */
|
||||
#define _HANDSHAKE 0x80
|
||||
#define _COMMAND 0x01
|
||||
|
||||
/* Key Repeat defines */
|
||||
#define _NO_BREAKS 0x08
|
||||
#define _NO_REPEATS 0x80
|
||||
|
||||
/* PS2_keystatus byte masks (from 16 bit int masks) */
|
||||
#define _BREAK ( PS2_BREAK >> 8 )
|
||||
#define _SHIFT ( PS2_SHIFT >> 8 )
|
||||
#define _CTRL ( PS2_CTRL >> 8 )
|
||||
#define _CAPS ( PS2_CAPS >> 8 )
|
||||
#define _ALT ( PS2_ALT >> 8 )
|
||||
#define _ALT_GR ( PS2_ALT_GR >> 8 )
|
||||
#define _GUI ( PS2_GUI >> 8 )
|
||||
#define _FUNCTION ( PS2_FUNCTION >> 8 )
|
||||
|
||||
/* General defines of comms codes */
|
||||
/* Command or response */
|
||||
#define PS2_KC_RESEND 0xFE
|
||||
#define PS2_KC_ACK 0xFA
|
||||
#define PS2_KC_ECHO 0xEE
|
||||
/* Responses */
|
||||
#define PS2_KC_BAT 0xAA
|
||||
// Actually buffer overrun
|
||||
#define PS2_KC_OVERRUN 0xFF
|
||||
// Below is general error code
|
||||
#define PS2_KC_ERROR 0xFC
|
||||
#define PS2_KC_KEYBREAK 0xF0
|
||||
#define PS2_KC_EXTEND1 0xE1
|
||||
#define PS2_KC_EXTEND 0xE0
|
||||
/* Commands */
|
||||
#define PS2_KC_RESET 0xFF
|
||||
#define PS2_KC_DEFAULTS 0xF6
|
||||
#define PS2_KC_DISABLE 0xF5
|
||||
#define PS2_KC_ENABLE 0xF4
|
||||
#define PS2_KC_RATE 0xF3
|
||||
#define PS2_KC_READID 0xF2
|
||||
#define PS2_KC_SCANCODE 0xF0
|
||||
#define PS2_KC_LOCK 0xED
|
||||
|
||||
/* Single Byte Key Codes */
|
||||
#define PS2_KC_NUM 0x77
|
||||
#define PS2_KC_SCROLL 0x7E
|
||||
#define PS2_KC_CAPS 0x58
|
||||
#define PS2_KC_L_SHIFT 0x12
|
||||
#define PS2_KC_R_SHIFT 0x59
|
||||
/* This is Left CTRL and ALT but Right version is in E0 with same code */
|
||||
#define PS2_KC_CTRL 0X14
|
||||
#define PS2_KC_ALT 0x11
|
||||
/* Generated by some keyboards by ALT and PRTSCR */
|
||||
#define PS2_KC_SYSRQ 0x84
|
||||
#define PS2_KC_ESC 0x76
|
||||
#define PS2_KC_BS 0x66
|
||||
#define PS2_KC_TAB 0x0D
|
||||
#define PS2_KC_ENTER 0x5A
|
||||
#define PS2_KC_SPACE 0x29
|
||||
#define PS2_KC_KP0 0x70
|
||||
#define PS2_KC_KP1 0x69
|
||||
#define PS2_KC_KP2 0x72
|
||||
#define PS2_KC_KP3 0x7A
|
||||
#define PS2_KC_KP4 0x6B
|
||||
#define PS2_KC_KP5 0x73
|
||||
#define PS2_KC_KP6 0x74
|
||||
#define PS2_KC_KP7 0x6C
|
||||
#define PS2_KC_KP8 0x75
|
||||
#define PS2_KC_KP9 0x7D
|
||||
#define PS2_KC_KP_DOT 0x71
|
||||
#define PS2_KC_KP_PLUS 0x79
|
||||
#define PS2_KC_KP_MINUS 0x7B
|
||||
#define PS2_KC_KP_TIMES 0x7C
|
||||
/* Some keyboards have an '=' on right keypad */
|
||||
#define PS2_KC_KP_EQUAL 0x0F
|
||||
#define PS2_KC_0 0X45
|
||||
#define PS2_KC_1 0X16
|
||||
#define PS2_KC_2 0X1E
|
||||
#define PS2_KC_3 0X26
|
||||
#define PS2_KC_4 0X25
|
||||
#define PS2_KC_5 0X2E
|
||||
#define PS2_KC_6 0X36
|
||||
#define PS2_KC_7 0X3D
|
||||
#define PS2_KC_8 0X3E
|
||||
#define PS2_KC_9 0X46
|
||||
#define PS2_KC_APOS 0X52
|
||||
#define PS2_KC_COMMA 0X41
|
||||
#define PS2_KC_MINUS 0X4E
|
||||
#define PS2_KC_DOT 0X49
|
||||
#define PS2_KC_DIV 0X4A
|
||||
/* Single quote or back apostrophe */
|
||||
#define PS2_KC_BTICK 0X0E
|
||||
#define PS2_KC_A 0X1C
|
||||
#define PS2_KC_B 0X32
|
||||
#define PS2_KC_C 0X21
|
||||
#define PS2_KC_D 0X23
|
||||
#define PS2_KC_E 0X24
|
||||
#define PS2_KC_F 0X2B
|
||||
#define PS2_KC_G 0X34
|
||||
#define PS2_KC_H 0X33
|
||||
#define PS2_KC_I 0X43
|
||||
#define PS2_KC_J 0X3B
|
||||
#define PS2_KC_K 0X42
|
||||
#define PS2_KC_L 0X4B
|
||||
#define PS2_KC_M 0X3A
|
||||
#define PS2_KC_N 0X31
|
||||
#define PS2_KC_O 0X44
|
||||
#define PS2_KC_P 0X4D
|
||||
#define PS2_KC_Q 0X15
|
||||
#define PS2_KC_R 0X2D
|
||||
#define PS2_KC_S 0X1B
|
||||
#define PS2_KC_T 0X2C
|
||||
#define PS2_KC_U 0X3C
|
||||
#define PS2_KC_V 0X2A
|
||||
#define PS2_KC_W 0X1D
|
||||
#define PS2_KC_X 0X22
|
||||
#define PS2_KC_Y 0X35
|
||||
#define PS2_KC_Z 0X1A
|
||||
#define PS2_KC_SEMI 0X4C
|
||||
#define PS2_KC_BACK 0X5D
|
||||
// Extra key left of Z on 102 keyboards
|
||||
#define PS2_KC_EUROPE2 0x61
|
||||
#define PS2_KC_OPEN_SQ 0X54
|
||||
#define PS2_KC_CLOSE_SQ 0X5B
|
||||
#define PS2_KC_EQUAL 0X55
|
||||
#define PS2_KC_F1 0X05
|
||||
#define PS2_KC_F2 0X06
|
||||
#define PS2_KC_F3 0X04
|
||||
#define PS2_KC_F4 0X0C
|
||||
#define PS2_KC_F5 0X03
|
||||
#define PS2_KC_F6 0X0B
|
||||
#define PS2_KC_F7 0X83
|
||||
#define PS2_KC_F8 0X0A
|
||||
#define PS2_KC_F9 0X01
|
||||
#define PS2_KC_F10 0X09
|
||||
#define PS2_KC_F11 0X78
|
||||
#define PS2_KC_F12 0X07
|
||||
#define PS2_KC_F13 0X08
|
||||
#define PS2_KC_F14 0X10
|
||||
#define PS2_KC_F15 0X18
|
||||
#define PS2_KC_F16 0X20
|
||||
#define PS2_KC_F17 0X28
|
||||
#define PS2_KC_F18 0X30
|
||||
#define PS2_KC_F19 0X38
|
||||
#define PS2_KC_F20 0X40
|
||||
#define PS2_KC_F21 0X48
|
||||
#define PS2_KC_F22 0X50
|
||||
#define PS2_KC_F23 0X57
|
||||
#define PS2_KC_F24 0X5F
|
||||
#define PS2_KC_KP_COMMA 0X6D
|
||||
#define PS2_KC_INTL1 0X51
|
||||
#define PS2_KC_INTL2 0X13
|
||||
#define PS2_KC_INTL3 0X6A
|
||||
#define PS2_KC_INTL4 0X64
|
||||
#define PS2_KC_INTL5 0X67
|
||||
#define PS2_KC_LANG1 0XF2
|
||||
#define PS2_KC_LANG2 0XF1
|
||||
#define PS2_KC_LANG3 0X63
|
||||
#define PS2_KC_LANG4 0X62
|
||||
#define PS2_KC_LANG5 0X5F
|
||||
|
||||
/* Extended key codes E0 table for two byte codes */
|
||||
/* PS2_CTRL and PS2_ALT Need using in any table for the right keys */
|
||||
/* first is special case for PRTSCR not always used so ignored by decoding */
|
||||
#define PS2_KC_IGNORE 0x12
|
||||
#define PS2_KC_PRTSCR 0x7C
|
||||
/* Sometimes called windows key */
|
||||
#define PS2_KC_L_GUI 0x1F
|
||||
#define PS2_KC_R_GUI 0x27
|
||||
#define PS2_KC_MENU 0x2F
|
||||
/* Break is CTRL + PAUSE generated inside keyboard */
|
||||
#define PS2_KC_BREAK 0x7E
|
||||
#define PS2_KC_HOME 0x6C
|
||||
#define PS2_KC_END 0x69
|
||||
#define PS2_KC_PGUP 0x7D
|
||||
#define PS2_KC_PGDN 0x7A
|
||||
#define PS2_KC_L_ARROW 0x6B
|
||||
#define PS2_KC_R_ARROW 0x74
|
||||
#define PS2_KC_UP_ARROW 0x75
|
||||
#define PS2_KC_DN_ARROW 0x72
|
||||
#define PS2_KC_INSERT 0x70
|
||||
#define PS2_KC_DELETE 0x71
|
||||
#define PS2_KC_KP_ENTER 0x5A
|
||||
#define PS2_KC_KP_DIV 0x4A
|
||||
#define PS2_KC_NEXT_TR 0X4D
|
||||
#define PS2_KC_PREV_TR 0X15
|
||||
#define PS2_KC_STOP 0X3B
|
||||
#define PS2_KC_PLAY 0X34
|
||||
#define PS2_KC_MUTE 0X23
|
||||
#define PS2_KC_VOL_UP 0X32
|
||||
#define PS2_KC_VOL_DN 0X21
|
||||
#define PS2_KC_MEDIA 0X50
|
||||
#define PS2_KC_EMAIL 0X48
|
||||
#define PS2_KC_CALC 0X2B
|
||||
#define PS2_KC_COMPUTER 0X40
|
||||
#define PS2_KC_WEB_SEARCH 0X10
|
||||
#define PS2_KC_WEB_HOME 0X3A
|
||||
#define PS2_KC_WEB_BACK 0X38
|
||||
#define PS2_KC_WEB_FORWARD 0X30
|
||||
#define PS2_KC_WEB_STOP 0X28
|
||||
#define PS2_KC_WEB_REFRESH 0X20
|
||||
#define PS2_KC_WEB_FAVOR 0X18
|
||||
#define PS2_KC_POWER 0X37
|
||||
#define PS2_KC_SLEEP 0X3F
|
||||
#define PS2_KC_WAKE 0X5E
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/PS2KeyTable.h
|
||||
393
main/include/PS2KeyTable.h
Normal file
393
main/include/PS2KeyTable.h
Normal file
@@ -0,0 +1,393 @@
|
||||
/* Version V1.0.8
|
||||
PS2KeyTable.h - PS2KeyAdvanced library keycode values to return values
|
||||
Copyright (c) 2007 Free Software Foundation. All right reserved.
|
||||
Written by Paul Carpenter, PC Services <sales@pcserviceselectronics.co.uk>
|
||||
Created September 2014
|
||||
V1.0.2 Updated January 2016 - Paul Carpenter - add tested on Due and tidy ups for V1.5 Library Management
|
||||
|
||||
PRIVATE to library
|
||||
|
||||
Test History
|
||||
September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0
|
||||
January 2016 Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board
|
||||
Manager V1.6.6
|
||||
|
||||
Internal to library private tables
|
||||
(may disappear in updates do not rely on this file or definitions)
|
||||
|
||||
This is for a LATIN style keyboard. Will support most keyboards even ones
|
||||
with multimedia keys or even 24 function keys.
|
||||
|
||||
Definitions used for key codes from a PS2 keyboard, do not use in your
|
||||
code these are handled by the library.
|
||||
|
||||
See PS2KeyAdvanced.h for codes returned from library and flag settings
|
||||
|
||||
Two sets of tables
|
||||
|
||||
Single Byte codes returned as key codes
|
||||
|
||||
Two byte Codes preceded by E0 code returned as keycodes
|
||||
|
||||
Same tables used for make and break decode
|
||||
|
||||
Special cases are -
|
||||
|
||||
PRTSCR that ignores one of the sequences (E0,12) as this is not always sent
|
||||
especially with modifier keys or some keyboards when typematic repeat comes on.
|
||||
|
||||
PAUSE as this is an 8 byte sequence only one starting E1 so main code gets E1
|
||||
and waits for 7 more valid bytes to make the coding.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef PS2KeyTable_h
|
||||
#define PS2KeyTable_h
|
||||
|
||||
/* Table contents are pairs of numbers
|
||||
first code from keyboard
|
||||
second is either PS2_KEY_IGNOPRE code or key code to return
|
||||
|
||||
Single byte Key table
|
||||
In codes can only be 1 - 0x9F, plus 0xF2 and 0xF1
|
||||
Out Codes in range 1 to 0x9F
|
||||
*/
|
||||
const uint8_t single_key[][ 2 ] = {
|
||||
{ PS2_KC_NUM, PS2_KEY_NUM },
|
||||
{ PS2_KC_SCROLL, PS2_KEY_SCROLL },
|
||||
{ PS2_KC_CAPS, PS2_KEY_CAPS },
|
||||
{ PS2_KC_L_SHIFT, PS2_KEY_L_SHIFT },
|
||||
{ PS2_KC_R_SHIFT, PS2_KEY_R_SHIFT },
|
||||
{ PS2_KC_CTRL, PS2_KEY_L_CTRL },
|
||||
{ PS2_KC_ALT, PS2_KEY_L_ALT },
|
||||
{ PS2_KC_SYSRQ, PS2_KEY_SYSRQ },
|
||||
{ PS2_KC_ESC, PS2_KEY_ESC },
|
||||
{ PS2_KC_BS, PS2_KEY_BS },
|
||||
{ PS2_KC_TAB, PS2_KEY_TAB },
|
||||
{ PS2_KC_ENTER, PS2_KEY_ENTER },
|
||||
{ PS2_KC_SPACE, PS2_KEY_SPACE },
|
||||
{ PS2_KC_KP0, PS2_KEY_KP0 },
|
||||
{ PS2_KC_KP1, PS2_KEY_KP1 },
|
||||
{ PS2_KC_KP2, PS2_KEY_KP2 },
|
||||
{ PS2_KC_KP3, PS2_KEY_KP3 },
|
||||
{ PS2_KC_KP4, PS2_KEY_KP4 },
|
||||
{ PS2_KC_KP5, PS2_KEY_KP5 },
|
||||
{ PS2_KC_KP6, PS2_KEY_KP6 },
|
||||
{ PS2_KC_KP7, PS2_KEY_KP7 },
|
||||
{ PS2_KC_KP8, PS2_KEY_KP8 },
|
||||
{ PS2_KC_KP9, PS2_KEY_KP9 },
|
||||
{ PS2_KC_KP_DOT, PS2_KEY_KP_DOT },
|
||||
{ PS2_KC_KP_PLUS, PS2_KEY_KP_PLUS },
|
||||
{ PS2_KC_KP_MINUS, PS2_KEY_KP_MINUS },
|
||||
{ PS2_KC_KP_TIMES, PS2_KEY_KP_TIMES },
|
||||
{ PS2_KC_KP_EQUAL, PS2_KEY_KP_EQUAL },
|
||||
{ PS2_KC_0, PS2_KEY_0 },
|
||||
{ PS2_KC_1, PS2_KEY_1 },
|
||||
{ PS2_KC_2, PS2_KEY_2 },
|
||||
{ PS2_KC_3, PS2_KEY_3 },
|
||||
{ PS2_KC_4, PS2_KEY_4 },
|
||||
{ PS2_KC_5, PS2_KEY_5 },
|
||||
{ PS2_KC_6, PS2_KEY_6 },
|
||||
{ PS2_KC_7, PS2_KEY_7 },
|
||||
{ PS2_KC_8, PS2_KEY_8 },
|
||||
{ PS2_KC_9, PS2_KEY_9 },
|
||||
{ PS2_KC_APOS, PS2_KEY_APOS },
|
||||
{ PS2_KC_COMMA, PS2_KEY_COMMA },
|
||||
{ PS2_KC_MINUS, PS2_KEY_MINUS },
|
||||
{ PS2_KC_DOT, PS2_KEY_DOT },
|
||||
{ PS2_KC_DIV, PS2_KEY_DIV },
|
||||
{ PS2_KC_BTICK, PS2_KEY_BTICK },
|
||||
{ PS2_KC_A, PS2_KEY_A },
|
||||
{ PS2_KC_B, PS2_KEY_B },
|
||||
{ PS2_KC_C, PS2_KEY_C },
|
||||
{ PS2_KC_D, PS2_KEY_D },
|
||||
{ PS2_KC_E, PS2_KEY_E },
|
||||
{ PS2_KC_F, PS2_KEY_F },
|
||||
{ PS2_KC_G, PS2_KEY_G },
|
||||
{ PS2_KC_H, PS2_KEY_H },
|
||||
{ PS2_KC_I, PS2_KEY_I },
|
||||
{ PS2_KC_J, PS2_KEY_J },
|
||||
{ PS2_KC_K, PS2_KEY_K },
|
||||
{ PS2_KC_L, PS2_KEY_L },
|
||||
{ PS2_KC_M, PS2_KEY_M },
|
||||
{ PS2_KC_N, PS2_KEY_N },
|
||||
{ PS2_KC_O, PS2_KEY_O },
|
||||
{ PS2_KC_P, PS2_KEY_P },
|
||||
{ PS2_KC_Q, PS2_KEY_Q },
|
||||
{ PS2_KC_R, PS2_KEY_R },
|
||||
{ PS2_KC_S, PS2_KEY_S },
|
||||
{ PS2_KC_T, PS2_KEY_T },
|
||||
{ PS2_KC_U, PS2_KEY_U },
|
||||
{ PS2_KC_V, PS2_KEY_V },
|
||||
{ PS2_KC_W, PS2_KEY_W },
|
||||
{ PS2_KC_X, PS2_KEY_X },
|
||||
{ PS2_KC_Y, PS2_KEY_Y },
|
||||
{ PS2_KC_Z, PS2_KEY_Z },
|
||||
{ PS2_KC_SEMI, PS2_KEY_SEMI },
|
||||
{ PS2_KC_BACK, PS2_KEY_HASH },
|
||||
{ PS2_KC_OPEN_SQ, PS2_KEY_OPEN_SQ },
|
||||
{ PS2_KC_CLOSE_SQ, PS2_KEY_CLOSE_SQ },
|
||||
{ PS2_KC_EQUAL, PS2_KEY_EQUAL },
|
||||
{ PS2_KC_EUROPE2, PS2_KEY_BACK },
|
||||
{ PS2_KC_F1, PS2_KEY_F1 },
|
||||
{ PS2_KC_F2, PS2_KEY_F2 },
|
||||
{ PS2_KC_F3, PS2_KEY_F3 },
|
||||
{ PS2_KC_F4, PS2_KEY_F4 },
|
||||
{ PS2_KC_F5, PS2_KEY_F5 },
|
||||
{ PS2_KC_F6, PS2_KEY_F6 },
|
||||
{ PS2_KC_F7, PS2_KEY_F7 },
|
||||
{ PS2_KC_F8, PS2_KEY_F8 },
|
||||
{ PS2_KC_F9, PS2_KEY_F9 },
|
||||
{ PS2_KC_F10, PS2_KEY_F10 },
|
||||
{ PS2_KC_F11, PS2_KEY_F11 },
|
||||
{ PS2_KC_F12, PS2_KEY_F12 },
|
||||
{ PS2_KC_KP_COMMA, PS2_KEY_KP_COMMA },
|
||||
{ PS2_KC_INTL1, PS2_KEY_INTL1 },
|
||||
{ PS2_KC_INTL2, PS2_KEY_INTL2 },
|
||||
{ PS2_KC_INTL3, PS2_KEY_INTL3 },
|
||||
{ PS2_KC_INTL4, PS2_KEY_INTL4 },
|
||||
{ PS2_KC_INTL5, PS2_KEY_INTL5 },
|
||||
{ PS2_KC_LANG1, PS2_KEY_LANG1 },
|
||||
{ PS2_KC_LANG2, PS2_KEY_LANG2 },
|
||||
{ PS2_KC_LANG3, PS2_KEY_LANG3 },
|
||||
{ PS2_KC_LANG4, PS2_KEY_LANG4 },
|
||||
{ PS2_KC_LANG5, PS2_KEY_LANG5 }
|
||||
};
|
||||
|
||||
/* Two byte Key table after an E0 byte received */
|
||||
const uint8_t extended_key[][ 2 ] = {
|
||||
{ PS2_KC_IGNORE, PS2_KEY_IGNORE },
|
||||
{ PS2_KC_PRTSCR, PS2_KEY_PRTSCR },
|
||||
{ PS2_KC_CTRL, PS2_KEY_R_CTRL },
|
||||
{ PS2_KC_ALT, PS2_KEY_R_ALT },
|
||||
{ PS2_KC_L_GUI, PS2_KEY_L_GUI },
|
||||
{ PS2_KC_R_GUI, PS2_KEY_R_GUI },
|
||||
{ PS2_KC_MENU, PS2_KEY_MENU },
|
||||
{ PS2_KC_BREAK, PS2_KEY_BREAK },
|
||||
{ PS2_KC_HOME, PS2_KEY_HOME },
|
||||
{ PS2_KC_END, PS2_KEY_END },
|
||||
{ PS2_KC_PGUP, PS2_KEY_PGUP },
|
||||
{ PS2_KC_PGDN, PS2_KEY_PGDN },
|
||||
{ PS2_KC_L_ARROW, PS2_KEY_L_ARROW },
|
||||
{ PS2_KC_R_ARROW, PS2_KEY_R_ARROW },
|
||||
{ PS2_KC_UP_ARROW, PS2_KEY_UP_ARROW },
|
||||
{ PS2_KC_DN_ARROW, PS2_KEY_DN_ARROW },
|
||||
{ PS2_KC_INSERT, PS2_KEY_INSERT },
|
||||
{ PS2_KC_DELETE, PS2_KEY_DELETE },
|
||||
{ PS2_KC_KP_ENTER, PS2_KEY_KP_ENTER },
|
||||
{ PS2_KC_KP_DIV, PS2_KEY_KP_DIV },
|
||||
{ PS2_KC_NEXT_TR, PS2_KEY_NEXT_TR },
|
||||
{ PS2_KC_PREV_TR, PS2_KEY_PREV_TR },
|
||||
{ PS2_KC_STOP, PS2_KEY_STOP },
|
||||
{ PS2_KC_PLAY, PS2_KEY_PLAY },
|
||||
{ PS2_KC_MUTE, PS2_KEY_MUTE },
|
||||
{ PS2_KC_VOL_UP, PS2_KEY_VOL_UP },
|
||||
{ PS2_KC_VOL_DN, PS2_KEY_VOL_DN },
|
||||
{ PS2_KC_MEDIA, PS2_KEY_MEDIA },
|
||||
{ PS2_KC_EMAIL, PS2_KEY_EMAIL },
|
||||
{ PS2_KC_CALC, PS2_KEY_CALC },
|
||||
{ PS2_KC_COMPUTER, PS2_KEY_COMPUTER },
|
||||
{ PS2_KC_WEB_SEARCH, PS2_KEY_WEB_SEARCH },
|
||||
{ PS2_KC_WEB_HOME, PS2_KEY_WEB_HOME },
|
||||
{ PS2_KC_WEB_BACK, PS2_KEY_WEB_BACK },
|
||||
{ PS2_KC_WEB_FORWARD, PS2_KEY_WEB_FORWARD },
|
||||
{ PS2_KC_WEB_STOP, PS2_KEY_WEB_STOP },
|
||||
{ PS2_KC_WEB_REFRESH, PS2_KEY_WEB_REFRESH },
|
||||
{ PS2_KC_WEB_FAVOR, PS2_KEY_WEB_FAVOR },
|
||||
{ PS2_KC_POWER, PS2_KEY_POWER },
|
||||
{ PS2_KC_SLEEP, PS2_KEY_SLEEP },
|
||||
{ PS2_KC_WAKE, PS2_KEY_WAKE }
|
||||
};
|
||||
|
||||
/* Scroll lock numeric keypad re-mappings for NOT NUMLOCK */
|
||||
/* in translated code order order is important */
|
||||
const uint8_t scroll_remap[] = {
|
||||
PS2_KEY_INSERT, // PS2_KEY_KP0
|
||||
PS2_KEY_END, // PS2_KEY_KP1
|
||||
PS2_KEY_DN_ARROW, // PS2_KEY_KP2
|
||||
PS2_KEY_PGDN, // PS2_KEY_KP3
|
||||
PS2_KEY_L_ARROW, // PS2_KEY_KP4
|
||||
PS2_KEY_IGNORE, // PS2_KEY_KP5
|
||||
PS2_KEY_R_ARROW, // PS2_KEY_KP6
|
||||
PS2_KEY_HOME, // PS2_KEY_KP7
|
||||
PS2_KEY_UP_ARROW, // PS2_KEY_KP8
|
||||
PS2_KEY_PGUP, // PS2_KEY_KP9
|
||||
PS2_KEY_DELETE // PS2_KEY_KP_DOT
|
||||
};
|
||||
|
||||
//const uint8_t single_key[][ 2 ] = {
|
||||
// { PS2_KC_NUM, PS2_KEY_NUM },
|
||||
// { PS2_KC_SCROLL, PS2_KEY_SCROLL },
|
||||
// { PS2_KC_CAPS, PS2_KEY_CAPS },
|
||||
// { PS2_KC_L_SHIFT, PS2_KEY_L_SHIFT },
|
||||
// { PS2_KC_R_SHIFT, PS2_KEY_R_SHIFT },
|
||||
// { PS2_KC_CTRL, PS2_KEY_L_CTRL },
|
||||
// { PS2_KC_ALT, PS2_KEY_L_ALT },
|
||||
// { PS2_KC_SYSRQ, PS2_KEY_SYSRQ },
|
||||
// { PS2_KC_ESC, PS2_KEY_ESC },
|
||||
// { PS2_KC_BS, PS2_KEY_BS },
|
||||
// { PS2_KC_TAB, PS2_KEY_TAB },
|
||||
// { PS2_KC_ENTER, PS2_KEY_ENTER },
|
||||
// { PS2_KC_SPACE, PS2_KEY_SPACE },
|
||||
// { PS2_KC_KP0, PS2_KEY_KP0 },
|
||||
// { PS2_KC_KP1, PS2_KEY_KP1 },
|
||||
// { PS2_KC_KP2, PS2_KEY_KP2 },
|
||||
// { PS2_KC_KP3, PS2_KEY_KP3 },
|
||||
// { PS2_KC_KP4, PS2_KEY_KP4 },
|
||||
// { PS2_KC_KP5, PS2_KEY_KP5 },
|
||||
// { PS2_KC_KP6, PS2_KEY_KP6 },
|
||||
// { PS2_KC_KP7, PS2_KEY_KP7 },
|
||||
// { PS2_KC_KP8, PS2_KEY_KP8 },
|
||||
// { PS2_KC_KP9, PS2_KEY_KP9 },
|
||||
// { PS2_KC_KP_DOT, PS2_KEY_KP_DOT },
|
||||
// { PS2_KC_KP_PLUS, PS2_KEY_KP_PLUS },
|
||||
// { PS2_KC_KP_MINUS, PS2_KEY_KP_MINUS },
|
||||
// { PS2_KC_KP_TIMES, PS2_KEY_KP_TIMES },
|
||||
// { PS2_KC_KP_EQUAL, PS2_KEY_KP_EQUAL },
|
||||
// { PS2_KC_0, PS2_KEY_0 },
|
||||
// { PS2_KC_1, PS2_KEY_1 },
|
||||
// { PS2_KC_2, PS2_KEY_2 },
|
||||
// { PS2_KC_3, PS2_KEY_3 },
|
||||
// { PS2_KC_4, PS2_KEY_4 },
|
||||
// { PS2_KC_5, PS2_KEY_5 },
|
||||
// { PS2_KC_6, PS2_KEY_6 },
|
||||
// { PS2_KC_7, PS2_KEY_7 },
|
||||
// { PS2_KC_8, PS2_KEY_8 },
|
||||
// { PS2_KC_9, PS2_KEY_9 },
|
||||
// { PS2_KC_APOS, PS2_KEY_APOS },
|
||||
// { PS2_KC_COMMA, PS2_KEY_COMMA },
|
||||
// { PS2_KC_MINUS, PS2_KEY_MINUS },
|
||||
// { PS2_KC_DOT, PS2_KEY_DOT },
|
||||
// { PS2_KC_DIV, PS2_KEY_DIV },
|
||||
// { PS2_KC_BTICK, PS2_KEY_BTICK },
|
||||
// { PS2_KC_A, PS2_KEY_A },
|
||||
// { PS2_KC_B, PS2_KEY_B },
|
||||
// { PS2_KC_C, PS2_KEY_C },
|
||||
// { PS2_KC_D, PS2_KEY_D },
|
||||
// { PS2_KC_E, PS2_KEY_E },
|
||||
// { PS2_KC_F, PS2_KEY_F },
|
||||
// { PS2_KC_G, PS2_KEY_G },
|
||||
// { PS2_KC_H, PS2_KEY_H },
|
||||
// { PS2_KC_I, PS2_KEY_I },
|
||||
// { PS2_KC_J, PS2_KEY_J },
|
||||
// { PS2_KC_K, PS2_KEY_K },
|
||||
// { PS2_KC_L, PS2_KEY_L },
|
||||
// { PS2_KC_M, PS2_KEY_M },
|
||||
// { PS2_KC_N, PS2_KEY_N },
|
||||
// { PS2_KC_O, PS2_KEY_O },
|
||||
// { PS2_KC_P, PS2_KEY_P },
|
||||
// { PS2_KC_Q, PS2_KEY_Q },
|
||||
// { PS2_KC_R, PS2_KEY_R },
|
||||
// { PS2_KC_S, PS2_KEY_S },
|
||||
// { PS2_KC_T, PS2_KEY_T },
|
||||
// { PS2_KC_U, PS2_KEY_U },
|
||||
// { PS2_KC_V, PS2_KEY_V },
|
||||
// { PS2_KC_W, PS2_KEY_W },
|
||||
// { PS2_KC_X, PS2_KEY_X },
|
||||
// { PS2_KC_Y, PS2_KEY_Y },
|
||||
// { PS2_KC_Z, PS2_KEY_Z },
|
||||
// { PS2_KC_SEMI, PS2_KEY_SEMI },
|
||||
// { PS2_KC_BACK, PS2_KEY_BACK },
|
||||
// { PS2_KC_OPEN_SQ, PS2_KEY_OPEN_SQ },
|
||||
// { PS2_KC_CLOSE_SQ, PS2_KEY_CLOSE_SQ },
|
||||
// { PS2_KC_EQUAL, PS2_KEY_EQUAL },
|
||||
// { PS2_KC_EUROPE2, PS2_KEY_BACK },
|
||||
// { PS2_KC_F1, PS2_KEY_F1 },
|
||||
// { PS2_KC_F2, PS2_KEY_F2 },
|
||||
// { PS2_KC_F3, PS2_KEY_F3 },
|
||||
// { PS2_KC_F4, PS2_KEY_F4 },
|
||||
// { PS2_KC_F5, PS2_KEY_F5 },
|
||||
// { PS2_KC_F6, PS2_KEY_F6 },
|
||||
// { PS2_KC_F7, PS2_KEY_F7 },
|
||||
// { PS2_KC_F8, PS2_KEY_F8 },
|
||||
// { PS2_KC_F9, PS2_KEY_F9 },
|
||||
// { PS2_KC_F10, PS2_KEY_F10 },
|
||||
// { PS2_KC_F11, PS2_KEY_F11 },
|
||||
// { PS2_KC_F12, PS2_KEY_F12 },
|
||||
// { PS2_KC_KP_COMMA, PS2_KEY_KP_COMMA },
|
||||
// { PS2_KC_INTL1, PS2_KEY_INTL1 },
|
||||
// { PS2_KC_INTL2, PS2_KEY_INTL2 },
|
||||
// { PS2_KC_INTL3, PS2_KEY_INTL3 },
|
||||
// { PS2_KC_INTL4, PS2_KEY_INTL4 },
|
||||
// { PS2_KC_INTL5, PS2_KEY_INTL5 },
|
||||
// { PS2_KC_LANG1, PS2_KEY_LANG1 },
|
||||
// { PS2_KC_LANG2, PS2_KEY_LANG2 },
|
||||
// { PS2_KC_LANG3, PS2_KEY_LANG3 },
|
||||
// { PS2_KC_LANG4, PS2_KEY_LANG4 },
|
||||
// { PS2_KC_LANG5, PS2_KEY_LANG5 }
|
||||
// };
|
||||
//
|
||||
///* Two byte Key table after an E0 byte received */
|
||||
//const uint8_t extended_key[][ 2 ] = {
|
||||
// { PS2_KC_IGNORE, PS2_KEY_IGNORE },
|
||||
// { PS2_KC_PRTSCR, PS2_KEY_PRTSCR },
|
||||
// { PS2_KC_CTRL, PS2_KEY_R_CTRL },
|
||||
// { PS2_KC_ALT, PS2_KEY_R_ALT },
|
||||
// { PS2_KC_L_GUI, PS2_KEY_L_GUI },
|
||||
// { PS2_KC_R_GUI, PS2_KEY_R_GUI },
|
||||
// { PS2_KC_MENU, PS2_KEY_MENU },
|
||||
// { PS2_KC_BREAK, PS2_KEY_BREAK },
|
||||
// { PS2_KC_HOME, PS2_KEY_HOME },
|
||||
// { PS2_KC_END, PS2_KEY_END },
|
||||
// { PS2_KC_PGUP, PS2_KEY_PGUP },
|
||||
// { PS2_KC_PGDN, PS2_KEY_PGDN },
|
||||
// { PS2_KC_L_ARROW, PS2_KEY_L_ARROW },
|
||||
// { PS2_KC_R_ARROW, PS2_KEY_R_ARROW },
|
||||
// { PS2_KC_UP_ARROW, PS2_KEY_UP_ARROW },
|
||||
// { PS2_KC_DN_ARROW, PS2_KEY_DN_ARROW },
|
||||
// { PS2_KC_INSERT, PS2_KEY_INSERT },
|
||||
// { PS2_KC_DELETE, PS2_KEY_DELETE },
|
||||
// { PS2_KC_KP_ENTER, PS2_KEY_KP_ENTER },
|
||||
// { PS2_KC_KP_DIV, PS2_KEY_KP_DIV },
|
||||
// { PS2_KC_NEXT_TR, PS2_KEY_NEXT_TR },
|
||||
// { PS2_KC_PREV_TR, PS2_KEY_PREV_TR },
|
||||
// { PS2_KC_STOP, PS2_KEY_STOP },
|
||||
// { PS2_KC_PLAY, PS2_KEY_PLAY },
|
||||
// { PS2_KC_MUTE, PS2_KEY_MUTE },
|
||||
// { PS2_KC_VOL_UP, PS2_KEY_VOL_UP },
|
||||
// { PS2_KC_VOL_DN, PS2_KEY_VOL_DN },
|
||||
// { PS2_KC_MEDIA, PS2_KEY_MEDIA },
|
||||
// { PS2_KC_EMAIL, PS2_KEY_EMAIL },
|
||||
// { PS2_KC_CALC, PS2_KEY_CALC },
|
||||
// { PS2_KC_COMPUTER, PS2_KEY_COMPUTER },
|
||||
// { PS2_KC_WEB_SEARCH, PS2_KEY_WEB_SEARCH },
|
||||
// { PS2_KC_WEB_HOME, PS2_KEY_WEB_HOME },
|
||||
// { PS2_KC_WEB_BACK, PS2_KEY_WEB_BACK },
|
||||
// { PS2_KC_WEB_FORWARD, PS2_KEY_WEB_FORWARD },
|
||||
// { PS2_KC_WEB_STOP, PS2_KEY_WEB_STOP },
|
||||
// { PS2_KC_WEB_REFRESH, PS2_KEY_WEB_REFRESH },
|
||||
// { PS2_KC_WEB_FAVOR, PS2_KEY_WEB_FAVOR },
|
||||
// { PS2_KC_POWER, PS2_KEY_POWER },
|
||||
// { PS2_KC_SLEEP, PS2_KEY_SLEEP },
|
||||
// { PS2_KC_WAKE, PS2_KEY_WAKE }
|
||||
// };
|
||||
//
|
||||
///* Scroll lock numeric keypad re-mappings for NOT NUMLOCK */
|
||||
///* in translated code order order is important */
|
||||
//const uint8_t scroll_remap[] = {
|
||||
// PS2_KEY_INSERT, // PS2_KEY_KP0
|
||||
// PS2_KEY_END, // PS2_KEY_KP1
|
||||
// PS2_KEY_DN_ARROW, // PS2_KEY_KP2
|
||||
// PS2_KEY_PGDN, // PS2_KEY_KP3
|
||||
// PS2_KEY_L_ARROW, // PS2_KEY_KP4
|
||||
// PS2_KEY_IGNORE, // PS2_KEY_KP5
|
||||
// PS2_KEY_R_ARROW, // PS2_KEY_KP6
|
||||
// PS2_KEY_HOME, // PS2_KEY_KP7
|
||||
// PS2_KEY_UP_ARROW, // PS2_KEY_KP8
|
||||
// PS2_KEY_PGUP, // PS2_KEY_KP9
|
||||
// PS2_KEY_DELETE // PS2_KEY_KP_DOT
|
||||
// };
|
||||
//
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/PS2Mouse.h
|
||||
187
main/include/PS2Mouse.h
Normal file
187
main/include/PS2Mouse.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: PS2Mouse.h
|
||||
// Created: Jan 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header file for the PS/2 Mouse Class.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef MOUSE_H_
|
||||
#define MOUSE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <functional>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "Arduino.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
|
||||
// PS/2 Mouse Class.
|
||||
class PS2Mouse {
|
||||
|
||||
// mode status flags
|
||||
#define _PS2_BUSY 0x04
|
||||
#define _TX_MODE 0x02
|
||||
#define _WAIT_RESPONSE 0x01
|
||||
|
||||
// Constants.
|
||||
#define MAX_PS2_XMIT_KEY_BUF 16
|
||||
#define MAX_PS2_RCV_KEY_BUF 16
|
||||
#define INTELLI_MOUSE 3
|
||||
#define SCALING_1_TO_1 0xE6
|
||||
#define DEFAULT_MOUSE_TIMEOUT 100
|
||||
|
||||
public:
|
||||
// Public structures used for containment of mouse movement and control data. These are used by the insantiating
|
||||
// object to request and process mouse data.
|
||||
// Postional data - X/Y co-ordinates of mouse movement.
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} Position;
|
||||
|
||||
// Mouse data, containing positional data, status, wheel data and validity.
|
||||
typedef struct {
|
||||
bool valid;
|
||||
bool overrun;
|
||||
int status;
|
||||
Position position;
|
||||
int wheel;
|
||||
} MouseData;
|
||||
|
||||
// Enumeration of all processed mouse responses.
|
||||
enum Responses {
|
||||
MOUSE_RESP_ACK = 0xFA,
|
||||
};
|
||||
|
||||
// Enumeration of all processed mouse commands.
|
||||
enum Commands {
|
||||
MOUSE_CMD_SET_SCALING_1_1 = 0xE6,
|
||||
MOUSE_CMD_SET_SCALING_2_1 = 0xE7,
|
||||
MOUSE_CMD_SET_RESOLUTION = 0xE8,
|
||||
MOUSE_CMD_GET_STATUS = 0xE9,
|
||||
MOUSE_CMD_SET_STREAM_MODE = 0xEA,
|
||||
MOUSE_CMD_REQUEST_DATA = 0xEB,
|
||||
MOUSE_CMD_SET_REMOTE_MODE = 0xF0,
|
||||
MOUSE_CMD_GET_DEVICE_ID = 0xF2,
|
||||
MOUSE_CMD_SET_SAMPLE_RATE = 0xF3,
|
||||
MOUSE_CMD_ENABLE_STREAMING = 0xF4,
|
||||
MOUSE_CMD_DISABLE_STREAMING = 0xF5,
|
||||
MOUSE_CMD_RESEND = 0xFE,
|
||||
MOUSE_CMD_RESET = 0xFF,
|
||||
};
|
||||
|
||||
// Resolution - the PS/2 mouse can digitize movement from 1mm to 1/8mm, the default being 1/4 (ie. 1mm = 4 counts). This allows configuration for a finer or rougher
|
||||
// tracking digitisation.
|
||||
enum PS2_RESOLUTION {
|
||||
PS2_MOUSE_RESOLUTION_1_1 = 0x00,
|
||||
PS2_MOUSE_RESOLUTION_1_2 = 0x01,
|
||||
PS2_MOUSE_RESOLUTION_1_4 = 0x02,
|
||||
PS2_MOUSE_RESOLUTION_1_8 = 0x03,
|
||||
};
|
||||
|
||||
// Scaling - the PS/2 mouse can provide linear (1:1 no scaling) or non liner (2:1 scaling) adaptation of the digitised data. This allows configuration for amplification of movements.
|
||||
enum PS2_SCALING {
|
||||
PS2_MOUSE_SCALING_1_1 = 0x00,
|
||||
PS2_MOUSE_SCALING_2_1 = 0x01,
|
||||
};
|
||||
|
||||
// Sampling rate - the PS/2 mouse, in streaming mode, the mouse sends with movement updates. This allows for finer or rougher digitisation of movements. The default is 100 samples per
|
||||
// second and the X68000 is fixed at 100 samples per second. Adjusting the ps/2 sample rate will affect tracking granularity on the X68000.
|
||||
enum PS2_SAMPLING {
|
||||
PS2_MOUSE_SAMPLE_RATE_10 = 10,
|
||||
PS2_MOUSE_SAMPLE_RATE_20 = 20,
|
||||
PS2_MOUSE_SAMPLE_RATE_40 = 40,
|
||||
PS2_MOUSE_SAMPLE_RATE_60 = 60,
|
||||
PS2_MOUSE_SAMPLE_RATE_80 = 80,
|
||||
PS2_MOUSE_SAMPLE_RATE_100 = 100,
|
||||
PS2_MOUSE_SAMPLE_RATE_200 = 200,
|
||||
};
|
||||
|
||||
// Public accessible prototypes.
|
||||
PS2Mouse(int clockPin, int dataPin);
|
||||
~PS2Mouse();
|
||||
void writeByte(uint8_t);
|
||||
bool setResolution(enum PS2_RESOLUTION resolution);
|
||||
bool setStreamMode(void);
|
||||
bool setRemoteMode(void);
|
||||
bool setScaling(enum PS2_SCALING scaling);
|
||||
char getDeviceId(void);
|
||||
bool checkIntelliMouseExtensions(void);
|
||||
bool setSampleRate(enum PS2_SAMPLING rate);
|
||||
bool enableStreaming(void);
|
||||
bool disableStreaming(void);
|
||||
bool getStatus(uint8_t *respBuf);
|
||||
bool reset(void);
|
||||
MouseData readData(void);
|
||||
void initialize(void);
|
||||
|
||||
// Method to register an object method for callback with context.
|
||||
template<typename A, typename B>
|
||||
void setMouseDataCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
ps2Ctrl.mouseDataCallback = bind(func_ptr, obj_ptr, 0, std::placeholders::_1);
|
||||
}
|
||||
|
||||
private:
|
||||
// PS/2 Control structure - maintains all data and variables relevant to forming a connection with a PS/2 mouse, interaction and processing of its data.
|
||||
struct {
|
||||
int clkPin; // Hardware clock pin - bidirectional.
|
||||
int dataPin; // Hardware data pin - bidirectional.
|
||||
volatile uint8_t mode; // mode contains _PS2_BUSY bit 2 = busy until all expected bytes RX/TX
|
||||
// _TX_MODE bit 1 = direction 1 = TX, 0 = RX (default)
|
||||
// _WAIT_RESPONSE bit 0 = expecting data response
|
||||
bool supportsIntelliMouseExtensions; // Intellimouse extensions supported.
|
||||
bool streamingEnabled; // Streaming mode has been enabled.
|
||||
volatile uint8_t bitCount; // Main state variable and bit count for interrupts
|
||||
volatile uint8_t shiftReg; // Incoming/Outgoing data shift register.
|
||||
volatile uint8_t parity; // Parity flag for data being sent/received.
|
||||
uint16_t rxBuf[16]; // RX buffer - assembled bytes are stored in this buffer awaiting processing.
|
||||
int rxPos; // Position in buffer to store next byte.
|
||||
|
||||
// Callback for streaming processed mouse data to HID handler.
|
||||
std::function<void(PS2Mouse::MouseData)> mouseDataCallback;
|
||||
} ps2Ctrl;
|
||||
|
||||
// Structure to store incoming streamed mouse data along with validity flags.
|
||||
struct {
|
||||
MouseData mouseData;
|
||||
bool newData; // An update has occurred since the last query.
|
||||
bool overrun; // A data overrun has occurred since the last query.
|
||||
} streaming;
|
||||
|
||||
// Interrupt handler - needs to be declared static and assigned to internal RAM (within the ESP32) to function correctly.
|
||||
IRAM_ATTR static void ps2interrupt( void );
|
||||
|
||||
// Prototypes.
|
||||
bool requestData(uint8_t expectedBytes, uint8_t *respBuf, uint32_t timeout);
|
||||
bool sendCmd(uint8_t cmd, uint8_t expectedBytes, uint8_t *respBuf, uint32_t timeout);
|
||||
|
||||
};
|
||||
|
||||
#endif // MOUSE_H_
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/SWITCH.h
|
||||
232
main/include/SWITCH.h
Normal file
232
main/include/SWITCH.h
Normal file
@@ -0,0 +1,232 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: SWITCH.h
|
||||
// Created: May 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Class definition to encapsulate the SharpKey WiFi/Config Switch.
|
||||
//
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2022 - Initial write.
|
||||
// v1.00 Jun 2022 - Updates to add additional callbacks for RESET and CLEARNVS
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SWITCH_H
|
||||
#define SWITCH_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "driver/timer.h"
|
||||
#include "LED.h"
|
||||
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Switch class.
|
||||
class SWITCH {
|
||||
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define SWITCH_VERSION 1.00
|
||||
|
||||
public:
|
||||
|
||||
// Prototypes.
|
||||
SWITCH(LED *led);
|
||||
SWITCH(void);
|
||||
virtual ~SWITCH(void);
|
||||
|
||||
// Method to register an object method for callback with context.
|
||||
template<typename A, typename B>
|
||||
void setCancelEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.cancelEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setCancelEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.cancelEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
// Wifi enable (configured mode).
|
||||
template<typename A, typename B>
|
||||
void setWifiEnEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.wifiEnEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setWifiEnEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.wifiEnEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
// Wifi default mode enable.
|
||||
template<typename A, typename B>
|
||||
void setWifiDefEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.wifiDefEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setWifiDefEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.wifiDefEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
// Bluetooth start pairing event.
|
||||
template<typename A, typename B>
|
||||
void setBTPairingEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.btPairingEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setBTPairingEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.btPairingEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
// RESET event - callback is executed prior to issuing an esp_restart().
|
||||
template<typename A, typename B>
|
||||
void setResetEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.resetEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setResetEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.resetEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
// CLEARNVS event - callback when user requests all NVS settings are erased.
|
||||
template<typename A, typename B>
|
||||
void setClearNVSEventCallback(A func_ptr, B obj_ptr)
|
||||
{
|
||||
swCtrl.clearNVSEventCallback = std::bind(func_ptr, obj_ptr);
|
||||
}
|
||||
template<typename A>
|
||||
void setClearNVSEventCallback(A func_ptr)
|
||||
{
|
||||
swCtrl.clearNVSEventCallback = std::bind(func_ptr);
|
||||
}
|
||||
|
||||
// Helper method to identify the sub class, this is used in non volatile key management.
|
||||
// Warning: This method wont work if optimisation for size is enabled on the compiler.
|
||||
const char *getClassName(const std::string& prettyFunction)
|
||||
{
|
||||
// First find the CLASS :: METHOD seperation.
|
||||
size_t colons = prettyFunction.find("::");
|
||||
|
||||
// None, then this is not a class.
|
||||
if (colons == std::string::npos)
|
||||
return "::";
|
||||
|
||||
// Split out the class name.
|
||||
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
|
||||
size_t end = colons - begin;
|
||||
|
||||
// Return the name.
|
||||
return(prettyFunction.substr(begin,end).c_str());
|
||||
}
|
||||
|
||||
// Helper method to change a file extension.
|
||||
void replaceExt(std::string& fileName, const std::string& newExt)
|
||||
{
|
||||
// Locals.
|
||||
std::string::size_type extPos = fileName.rfind('.', fileName.length());
|
||||
|
||||
if(extPos != std::string::npos)
|
||||
{
|
||||
fileName.replace(extPos+1, newExt.length(), newExt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Template to aid in conversion of an enum to integer.
|
||||
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept
|
||||
{
|
||||
return static_cast<typename std::underlying_type<E>::type>(e);
|
||||
}
|
||||
|
||||
// Method to return the class version number.
|
||||
virtual float version(void)
|
||||
{
|
||||
return(SWITCH_VERSION);
|
||||
}
|
||||
|
||||
// Method to return the name of the class.
|
||||
virtual std::string ifName(void)
|
||||
{
|
||||
return(swCtrl.swClassName);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
// Prototypes.
|
||||
void init(void);
|
||||
IRAM_ATTR static void swInterface( void * pvParameters );
|
||||
inline uint32_t milliSeconds(void)
|
||||
{
|
||||
return( (uint32_t) clock() );
|
||||
}
|
||||
|
||||
// Structure to maintain an active setting for the LED. The LED control thread uses these values to effect the required lighting of the LED.
|
||||
typedef struct {
|
||||
// Name of the class for this instantiation.
|
||||
std::string swClassName;
|
||||
|
||||
// Thread handles - Switch interface.
|
||||
TaskHandle_t TaskSWIF = NULL;
|
||||
|
||||
// Callback for Cancel Event.
|
||||
std::function<void(void)> cancelEventCallback;
|
||||
|
||||
// Callback for WiFi Enable Event.
|
||||
std::function<void(void)> wifiEnEventCallback;
|
||||
|
||||
// Callback for WiFi Default Event.
|
||||
std::function<void(void)> wifiDefEventCallback;
|
||||
|
||||
// Callback for Bluetooth Pairing Event.
|
||||
std::function<void(void)> btPairingEventCallback;
|
||||
|
||||
// Callback is executed prior to issuing an esp_restart().
|
||||
std::function<bool(void)> resetEventCallback;
|
||||
|
||||
// Callback when user requests all NVS settings are erased.
|
||||
std::function<void(void)> clearNVSEventCallback;
|
||||
} t_swControl;
|
||||
|
||||
// Var to store all SWITCH control variables.
|
||||
t_swControl swCtrl;
|
||||
|
||||
// LED activity object handle.
|
||||
LED *led;
|
||||
};
|
||||
#endif // SWITCH_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/WiFi.h
|
||||
400
main/include/WiFi.h
Normal file
400
main/include/WiFi.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: WiFi.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the WiFi AP/Client logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Seperated out the WiFi Enable switch and made the WiFi module active/
|
||||
// via a reboot process. This is necessary now that Bluetooth is inbuilt
|
||||
// as the ESP32 shares an antenna and both operating together electrically
|
||||
// is difficult but also the IDF stack conflicts as well.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WIFI_H
|
||||
#define WIFI_H
|
||||
|
||||
#if defined(CONFIG_IF_WIFI_ENABLED)
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <esp_http_server.h>
|
||||
#include "esp_littlefs.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <arpa/inet.h>
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
|
||||
// Encapsulate the WiFi functionality.
|
||||
class WiFi {
|
||||
// Constants.
|
||||
#define WIFI_VERSION 1.02
|
||||
#define OBJECT_VERSION_LIST_MAX 18
|
||||
#define FILEPACK_VERSION_FILE "version.txt"
|
||||
#define WIFI_AP_DEFAULT_IP "192.168.4.1"
|
||||
#define WIFI_AP_DEFAULT_GW "192.168.4.1"
|
||||
#define WIFI_AP_DEFAULT_NETMASK "255.255.255.0"
|
||||
|
||||
// The event group allows multiple bits for each event, but we only care about two events:
|
||||
// - we are connected to the AP with an IP
|
||||
// - we failed to connect after the maximum amount of retries
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
// Tag for ESP WiFi logging.
|
||||
#define WIFITAG "WiFi"
|
||||
|
||||
// Menu selection types.
|
||||
enum WIFIMODES {
|
||||
WIFI_OFF = 0x00, // WiFi is disabled.
|
||||
WIFI_ON = 0x01, // WiFi is enabled.
|
||||
WIFI_CONFIG_AP = 0x02, // WiFi is set to enable Access Point to configure WiFi settings.
|
||||
WIFI_CONFIG_CLIENT = 0x03 // WiFi is set to enable Client mode using persisted settings.
|
||||
};
|
||||
|
||||
// Default WiFi parameters.
|
||||
#define MAX_WIFI_SSID_LEN 31
|
||||
#define MAX_WIFI_PWD_LEN 63
|
||||
#define MAX_WIFI_IP_LEN 15
|
||||
#define MAX_WIFI_NETMASK_LEN 15
|
||||
#define MAX_WIFI_GATEWAY_LEN 15
|
||||
|
||||
// Buffer size for sending file data in chunks to the browser.
|
||||
#define MAX_CHUNK_SIZE 4096
|
||||
|
||||
// Max length a file path can have on the embedded storage device.
|
||||
#define FILE_PATH_MAX (15 + CONFIG_LITTLEFS_OBJ_NAME_LEN)
|
||||
|
||||
public:
|
||||
// Types for holding and maintaining a class/object to version number array.
|
||||
typedef struct {
|
||||
std::string object;
|
||||
float version;
|
||||
} t_versionItem;
|
||||
typedef struct {
|
||||
int elements;
|
||||
t_versionItem *item[OBJECT_VERSION_LIST_MAX];
|
||||
} t_versionList;
|
||||
|
||||
// Prototypes.
|
||||
WiFi(KeyInterface *hdlKeyIf, KeyInterface *hdlMouseIf, bool defaultMode, NVS *nvs, LED *led, const char *fsPath, t_versionList *versionList);
|
||||
WiFi(void);
|
||||
~WiFi(void);
|
||||
void run(void);
|
||||
|
||||
// Primary encapsulated interface object handle.
|
||||
KeyInterface *keyIf;
|
||||
|
||||
// Secondary encapsulated interface object handle.
|
||||
KeyInterface *mouseIf;
|
||||
|
||||
// Non Volatile Storage handle.
|
||||
NVS *nvs;
|
||||
|
||||
// LED activity handle.
|
||||
LED *led;
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(WIFI_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
// Type for key:value pairs.
|
||||
typedef struct {
|
||||
std::string name;
|
||||
std::string value;
|
||||
} t_kvPair;
|
||||
|
||||
// Structure to maintain wifi configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
// Client access parameters, these, when valid, are used for binding to a known wifi access point.
|
||||
struct {
|
||||
bool valid;
|
||||
char ssid[MAX_WIFI_SSID_LEN+1];
|
||||
char pwd[MAX_WIFI_PWD_LEN+1];
|
||||
bool useDHCP;
|
||||
char ip[MAX_WIFI_IP_LEN+1];
|
||||
char netmask[MAX_WIFI_NETMASK_LEN+1];
|
||||
char gateway[MAX_WIFI_GATEWAY_LEN+1];
|
||||
} clientParams;
|
||||
|
||||
// Structure to maintain Access Point parameters. These are configurable to allow possibility of changing them.
|
||||
struct {
|
||||
char ssid[MAX_WIFI_SSID_LEN+1];
|
||||
char pwd[MAX_WIFI_PWD_LEN+1];
|
||||
char ip[MAX_WIFI_IP_LEN+1];
|
||||
char netmask[MAX_WIFI_NETMASK_LEN+1];
|
||||
char gateway[MAX_WIFI_GATEWAY_LEN+1];
|
||||
} apParams;
|
||||
|
||||
// General runtime control parameters.
|
||||
struct {
|
||||
// Configured mode of the Wifi: Access Point or Client.
|
||||
enum WIFIMODES wifiMode;
|
||||
} params;
|
||||
} t_wifiConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_wifiConfig wifiConfig;
|
||||
|
||||
// Structure to manage the WiFi control variables, signifying the state of the Client or Access Point, runtime dependent, and
|
||||
// necessary dedicated run variables (as opposed to locals).
|
||||
typedef struct {
|
||||
// Client mode variables, active when in client mode.
|
||||
struct {
|
||||
int clientRetryCnt;
|
||||
bool connected;
|
||||
char ssid[MAX_WIFI_SSID_LEN+1];
|
||||
char pwd[MAX_WIFI_PWD_LEN+1];
|
||||
char ip[MAX_WIFI_IP_LEN+1];
|
||||
char netmask[MAX_WIFI_NETMASK_LEN+1];
|
||||
char gateway[MAX_WIFI_GATEWAY_LEN+1];
|
||||
} client;
|
||||
|
||||
// Access Point mode variabls, active when in AP mode.
|
||||
struct {
|
||||
char ssid[MAX_WIFI_SSID_LEN+1];
|
||||
char pwd[MAX_WIFI_PWD_LEN+1];
|
||||
char ip[MAX_WIFI_IP_LEN+1];
|
||||
char netmask[MAX_WIFI_NETMASK_LEN+1];
|
||||
char gateway[MAX_WIFI_GATEWAY_LEN+1];
|
||||
} ap;
|
||||
|
||||
// HTTP session variables, parsed out of incoming connections. The sessions are synchronous so only maintain
|
||||
// one copy.
|
||||
struct {
|
||||
std::string host;
|
||||
std::string queryStr;
|
||||
std::string fileName;
|
||||
std::string filePath;
|
||||
bool gzip;
|
||||
bool deflate;
|
||||
} session;
|
||||
|
||||
// Runtime variables, used for global control of the WiFi module.
|
||||
//
|
||||
struct {
|
||||
// Default path on the underlying filesystem. This is where the NVS/SD partition is mounted and all files under this directory are accessible.
|
||||
const char * fsPath;
|
||||
|
||||
// Version list of all objects used to build the SharpKey interface along with their version numbers.
|
||||
t_versionList *versionList;
|
||||
|
||||
// Run mode of the Wifi: Off, On or Access Point.
|
||||
enum WIFIMODES wifiMode;
|
||||
|
||||
// Handle to http server.
|
||||
httpd_handle_t server;
|
||||
|
||||
// Class name, used for NVS keys.
|
||||
std::string thisClass;
|
||||
|
||||
// Flag to raise a reboot button on the displayed page.
|
||||
bool rebootButton;
|
||||
|
||||
// Flag to indicate a hard reboot needed.
|
||||
bool reboot;
|
||||
|
||||
// Base path of file storag.
|
||||
char basePath[FILE_PATH_MAX];
|
||||
|
||||
// String to hold any response error message.
|
||||
std::string errorMsg;
|
||||
} run;
|
||||
} t_wifiControl;
|
||||
|
||||
// Control data.
|
||||
t_wifiControl wifiCtrl;
|
||||
|
||||
// Prototypes.
|
||||
bool setupWifiClient(void);
|
||||
bool setupWifiAP(void);
|
||||
bool stopWifi(void);
|
||||
bool startWebserver(void);
|
||||
void stopWebserver(void);
|
||||
float getVersionNumber(std::string name);
|
||||
esp_err_t expandAndSendFile(httpd_req_t *req, const char *basePath, std::string fileName);
|
||||
esp_err_t expandVarsAndSend(httpd_req_t *req, std::string str);
|
||||
esp_err_t sendKeyMapHeaders(httpd_req_t *req);
|
||||
esp_err_t sendKeyMapTypes(httpd_req_t *req);
|
||||
esp_err_t sendKeyMapCustomTypeFields(httpd_req_t *req);
|
||||
esp_err_t sendKeyMapData(httpd_req_t *req);
|
||||
esp_err_t sendKeyMapPopovers(httpd_req_t *req);
|
||||
esp_err_t sendMouseRadioChoice(httpd_req_t *req, const char *option);
|
||||
|
||||
|
||||
|
||||
esp_err_t wifiDataPOSTHandler(httpd_req_t *req, std::vector<t_kvPair> pairs, std::string& resp);
|
||||
esp_err_t mouseDataPOSTHandler(httpd_req_t *req, std::vector<t_kvPair> pairs, std::string& resp);
|
||||
static esp_err_t defaultDataPOSTHandler(httpd_req_t *req);
|
||||
static esp_err_t defaultDataGETHandler(httpd_req_t *req);
|
||||
IRAM_ATTR static esp_err_t otaFirmwareUpdatePOSTHandler(httpd_req_t *req);
|
||||
IRAM_ATTR static esp_err_t otaFilepackUpdatePOSTHandler(httpd_req_t *req);
|
||||
static esp_err_t keymapUploadPOSTHandler(httpd_req_t *req);
|
||||
static esp_err_t keymapTablePOSTHandler(httpd_req_t *req);
|
||||
|
||||
static esp_err_t defaultRebootHandler(httpd_req_t *req);
|
||||
esp_err_t getPOSTData(httpd_req_t *req, std::vector<t_kvPair> *pairs);
|
||||
|
||||
bool isFileExt(std::string fileName, std::string extension);
|
||||
esp_err_t setContentTypeFromFileType(httpd_req_t *req, std::string fileName);
|
||||
esp_err_t getPathFromURI(std::string& destPath, std::string& destFile, const char *basePath, const char *uri);
|
||||
esp_err_t getPathFromURI(std::string& destPath, const char *basePath, const char *uri);
|
||||
static esp_err_t defaultFileHandler(httpd_req_t *req);
|
||||
std::string esp32PartitionType(esp_partition_type_t type);
|
||||
std::string esp32PartitionSubType(esp_partition_subtype_t subtype);
|
||||
|
||||
|
||||
IRAM_ATTR static void pairBluetoothDevice(void *pvParameters);
|
||||
IRAM_ATTR static void wifiAPHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
IRAM_ATTR static void wifiClientHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
|
||||
// Method to split a string based on a delimiter and store in a vector.
|
||||
std::vector<std::string> split(std::string s, std::string delimiter)
|
||||
{
|
||||
// Locals.
|
||||
size_t pos_start = 0;
|
||||
size_t pos_end;
|
||||
size_t delim_len = delimiter.length();
|
||||
std::string token;
|
||||
std::vector<std::string> res;
|
||||
|
||||
// Loop through the string locating delimiters and split on each occurrence.
|
||||
while((pos_end = s.find (delimiter, pos_start)) != std::string::npos)
|
||||
{
|
||||
token = s.substr (pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
// Push each occurrence onto Vector.
|
||||
res.push_back (token);
|
||||
}
|
||||
|
||||
// Store last item in vector.
|
||||
res.push_back (s.substr (pos_start));
|
||||
return res;
|
||||
}
|
||||
|
||||
// check if a given string is a numeric string or not
|
||||
bool isNumber(const std::string &str)
|
||||
{
|
||||
// `std::find_first_not_of` searches the string for the first character
|
||||
// that does not match any of the characters specified in its arguments
|
||||
return !str.empty() &&
|
||||
(str.find_first_not_of("[0123456789]") == std::string::npos);
|
||||
}
|
||||
|
||||
// Function to split string `str` using a given delimiter
|
||||
std::vector<std::string> split(const std::string &str, char delim)
|
||||
{
|
||||
auto i = 0;
|
||||
std::vector<std::string> list;
|
||||
|
||||
auto pos = str.find(delim);
|
||||
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
list.push_back(str.substr(i, pos - i));
|
||||
i = ++pos;
|
||||
pos = str.find(delim, pos);
|
||||
}
|
||||
|
||||
list.push_back(str.substr(i, str.length()));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// Function to validate an IP address
|
||||
bool validateIP(std::string ip)
|
||||
{
|
||||
// split the string into tokens
|
||||
std::vector<std::string> list = split(ip, '.');
|
||||
|
||||
// if the token size is not equal to four
|
||||
if (list.size() != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate each token
|
||||
for (std::string str: list)
|
||||
{
|
||||
// verify that the string is a number or not, and the numbers
|
||||
// are in the valid range
|
||||
if (!isNumber(str) || std::stoi(str) > 255 || std::stoi(str) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method to split an IP4 address into its components, checking each for validity.
|
||||
bool splitIP(std::string ip, int *a, int *b, int *c, int *d)
|
||||
{
|
||||
// Init.
|
||||
*a = *b = *c = *d = 0;
|
||||
|
||||
// split the string into tokens
|
||||
std::vector<std::string> list = split(ip, '.');
|
||||
|
||||
// if the token size is not equal to four
|
||||
if (list.size() != 4) {
|
||||
printf("Size:%d\n", list.size());
|
||||
return false;
|
||||
}
|
||||
// Loop through vector and check each number for validity before assigning.
|
||||
for(int idx=0; idx < 4; idx++)
|
||||
{
|
||||
// verify that the string is a number or not, and the numbers
|
||||
// are in the valid range
|
||||
if (!isNumber(list.at(idx)) || std::stoi(list.at(idx)) > 255 || std::stoi(list.at(idx)) < 0) {
|
||||
printf("Item:%d, %s\n", idx, list.at(idx).c_str());
|
||||
return false;
|
||||
}
|
||||
int frag = std::stoi(list.at(idx));
|
||||
if(idx == 0) *a = frag;
|
||||
if(idx == 1) *b = frag;
|
||||
if(idx == 2) *c = frag;
|
||||
if(idx == 3) *d = frag;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // WIFI_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/X1.h
|
||||
687
main/include/X1.h
Normal file
687
main/include/X1.h
Normal file
@@ -0,0 +1,687 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: X1.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the Sharp X1 to PS/2 interface logic.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
// v1.03 Jun 2022 - Further updates adding in keymaps for UK BT and Japan OADG109.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef X1_H
|
||||
#define X1_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the Sharp X1 interface.
|
||||
class X1 : public KeyInterface {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define X1IF_VERSION 1.03
|
||||
#define X1IF_KEYMAP_FILE "X1_KeyMap.BIN"
|
||||
#define MAX_X1_XMIT_KEY_BUF 16
|
||||
#define PS2TBL_X1_MAXROWS 349
|
||||
|
||||
// X1 Key control bit mask.
|
||||
#define X1_CTRL_TENKEY ((unsigned char) (1 << 7))
|
||||
#define X1_CTRL_PRESS ((unsigned char) (1 << 6))
|
||||
#define X1_CTRL_REPEAT ((unsigned char) (1 << 5))
|
||||
#define X1_CTRL_GRAPH ((unsigned char) (1 << 4))
|
||||
#define X1_CTRL_CAPS ((unsigned char) (1 << 3))
|
||||
#define X1_CTRL_KANA ((unsigned char) (1 << 2))
|
||||
#define X1_CTRL_SHIFT ((unsigned char) (1 << 1))
|
||||
#define X1_CTRL_CTRL ((unsigned char) (1 << 0))
|
||||
|
||||
// X1 Special Key definitions.
|
||||
#define X1KEY_UP 0x1E // ↑
|
||||
#define X1KEY_DOWN 0x1F // ↓
|
||||
#define X1KEY_LEFT 0x1D // ←
|
||||
#define X1KEY_RIGHT 0x1C // → →
|
||||
#define X1KEY_INS 0x12 // INS
|
||||
#define X1KEY_DEL 0x08 // DEL
|
||||
#define X1KEY_CLR 0x0C // CLR
|
||||
#define X1KEY_HOME 0x0B // HOME
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2CTRL_NONE 0x00 // No keys active = 0
|
||||
#define PS2CTRL_SHIFT 0x01 // Shfit Key active = 1
|
||||
#define PS2CTRL_CTRL 0x02 // Ctrl Key active = 1
|
||||
#define PS2CTRL_CAPS 0x04 // CAPS active = 1
|
||||
#define PS2CTRL_KANA 0x08 // KANA active = 1
|
||||
#define PS2CTRL_GRAPH 0x10 // GRAPH active = 1
|
||||
#define PS2CTRL_GUI 0x20 // GUI Key active = 1
|
||||
#define PS2CTRL_FUNC 0x40 // Special Function Keys active = 1
|
||||
#define PS2CTRL_BREAK 0x80 // BREAK Key active = 1
|
||||
#define PS2CTRL_EXACT 0x80 // EXACT Match active = 1
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to extract the X1 key code and control data.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> X1 Key Code + Ctrl Data
|
||||
|
||||
// Keyboard mapping table column names.
|
||||
#define PS2TBL_PS2KEYCODE_NAME "PS/2 KeyCode"
|
||||
#define PS2TBL_PS2CTRL_NAME "PS/2 Control Key"
|
||||
#define PS2TBL_KEYBOARDMODEL_NAME "For Keyboard"
|
||||
#define PS2TBL_MACHINE_NAME "For Host Model"
|
||||
#define PS2TBL_X1MODE_NAME "X1 Mode"
|
||||
#define PS2TBL_X1KEYCODE_NAME "X1 KeyCode 1"
|
||||
#define PS2TBL_X1KEYCODE_BYTE2_NAME "X1 KeyCode 2"
|
||||
#define PS2TBL_X1_CTRL_NAME "X1 Control Key"
|
||||
|
||||
// Keyboard mapping table column types.
|
||||
#define PS2TBL_PS2KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PS2CTRL_TYPE "custom_cbp_ps2ctrl"
|
||||
#define PS2TBL_KEYBOARDMODEL_TYPE "custom_cbp_keybmodel"
|
||||
#define PS2TBL_MACHINE_TYPE "custom_cbp_machine"
|
||||
#define PS2TBL_X1MODE_TYPE "custom_cbp_x1mode"
|
||||
#define PS2TBL_X1KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_X1KEYCODE_BYTE2_TYPE "hex"
|
||||
#define PS2TBL_X1CTRL_TYPE "custom_cbn_x1ctrl"
|
||||
|
||||
// Keyboard mapping table select list for PS2CTRL.
|
||||
#define PS2TBL_PS2CTRL_SEL_NONE "NONE"
|
||||
#define PS2TBL_PS2CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PS2TBL_PS2CTRL_SEL_CTRL "CTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_CAPS "CAPS"
|
||||
#define PS2TBL_PS2CTRL_SEL_KANA "KANA"
|
||||
#define PS2TBL_PS2CTRL_SEL_GRAPH "GRAPH"
|
||||
#define PS2TBL_PS2CTRL_SEL_GUI "GUI"
|
||||
#define PS2TBL_PS2CTRL_SEL_FUNC "FUNC"
|
||||
#define PS2TBL_PS2CTRL_SEL_EXACT "EXACT"
|
||||
|
||||
// Keyboard mapping table select list for Model of keyboard.
|
||||
#define KEYMAP_SEL_STANDARD "ALL"
|
||||
#define KEYMAP_SEL_UK_WYSE_KB3926 "UK_WYSE_KB3926"
|
||||
#define KEYMAP_SEL_JAPAN_OADG109 "JAPAN_OADG109"
|
||||
#define KEYMAP_SEL_JAPAN_SANWA_SKBL1 "JAPAN_SANWA_SKBL1"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_4 "KEYBOARD_4"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_5 "KEYBOARD_5"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_6 "KEYBOARD_6"
|
||||
#define KEYMAP_SEL_UK_PERIBOARD_810 "UK_PERIBOARD_810"
|
||||
#define KEYMAP_SEL_UK_OMOTON_K8508 "UK_OMOTON_K8508"
|
||||
|
||||
// Keyboard mapping table select list for keyboard mode.
|
||||
#define X1_SEL_MODE_A "Mode_A"
|
||||
#define X1_SEL_MODE_B "Mode_B"
|
||||
|
||||
// Keyboard mapping table select list for target machine.
|
||||
#define X1_SEL_ALL "ALL"
|
||||
#define X1_SEL_ORIG "ORIGINAL"
|
||||
#define X1_SEL_TURBO "TURBO"
|
||||
#define X1_SEL_TURBOZ "TURBOZ"
|
||||
|
||||
// Keyboard mapping table select list for X1 Control codes.
|
||||
#define X1_CTRL_SEL_TENKEY "TENKEY"
|
||||
#define X1_CTRL_SEL_PRESS "PRESS"
|
||||
#define X1_CTRL_SEL_REPEAT "REPEAT"
|
||||
#define X1_CTRL_SEL_GRAPH "GRAPH"
|
||||
#define X1_CTRL_SEL_CAPS "CAPS"
|
||||
#define X1_CTRL_SEL_KANA "KANA"
|
||||
#define X1_CTRL_SEL_SHIFT "SHIFT"
|
||||
#define X1_CTRL_SEL_CTRL "CTRL"
|
||||
|
||||
// The Sharp X1 Series was released over a number of years and each iteration added changes/updates. In order to cater for differences, it is possible to assign a key mapping
|
||||
// to a specific machine type(s) or all of the series by adding the flags below into the mapping table.
|
||||
#define X1_ALL 0xFF
|
||||
#define X1_ORIG 0x01
|
||||
#define X1_TURBO 0x02
|
||||
#define X1_TURBOZ 0x04
|
||||
|
||||
// The X1 Turbo onwards had a mode switch on the keyboard, Mode A was normal use, Mode B was for games, speeding up the key press by shortening the timing and setting common game keys pressed in a 24bit bit map.
|
||||
// The mapping table caters for both, OR'ing data in Mode B so that multiple key presses are sent across as a bit map.
|
||||
#define X1_MODE_A 0x01
|
||||
#define X1_MODE_B 0x02
|
||||
|
||||
// Keyboard models. The base on which this interface was created was a Wyse KB3926 PS/2 Keyboard and this is deemed STANDARD. Other models need to insert difference maps
|
||||
// prior to the STANDARD entry along with the keyboard model so that it is processed first thus allowing differing keyboards with different maps.
|
||||
#define KEYMAP_STANDARD 0xFF
|
||||
#define KEYMAP_UK_WYSE_KB3926 0x01
|
||||
#define KEYMAP_JAPAN_OADG109 0x02
|
||||
#define KEYMAP_JAPAN_SANWA_SKBL1 0x04
|
||||
#define KEYMAP_NOT_ASSIGNED_4 0x08
|
||||
#define KEYMAP_NOT_ASSIGNED_5 0x10
|
||||
#define KEYMAP_NOT_ASSIGNED_6 0x20
|
||||
#define KEYMAP_UK_PERIBOARD_810 0x40
|
||||
#define KEYMAP_UK_OMOTON_K8508 0x80
|
||||
|
||||
public:
|
||||
// Prototypes.
|
||||
X1(void);
|
||||
X1(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, const char *fsPath);
|
||||
X1(NVS *hdlNVS, HID *hdlHID, const char *fsPath);
|
||||
~X1(void);
|
||||
bool createKeyMapFile(std::fstream &outFile);
|
||||
bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size);
|
||||
bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray);
|
||||
bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly);
|
||||
std::string getKeyMapFileName(void) { return(X1IF_KEYMAP_FILE); };
|
||||
void getKeyMapHeaders(std::vector<std::string>& headerList);
|
||||
void getKeyMapTypes(std::vector<std::string>& typeList);
|
||||
bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start);
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(X1IF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
void pushKeyToQueue(bool keybMode, uint32_t key);
|
||||
IRAM_ATTR static void x1Interface( void * pvParameters );
|
||||
IRAM_ATTR static void hidInterface( void * pvParameters );
|
||||
void selectOption(uint8_t optionCode);
|
||||
uint32_t mapKey(uint16_t scanCode);
|
||||
bool loadKeyMap();
|
||||
bool saveKeyMap(void);
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// // Overload the base yield method to include suspension of the PS/2 Keyboard interface. This interface uses interrupts which are not mutex protected and clash with the
|
||||
// // WiFi API methods.
|
||||
// inline void yield(uint32_t delay)
|
||||
// {
|
||||
// // If suspended, go into a permanent loop until the suspend flag is reset.
|
||||
// if(this->suspend)
|
||||
// {
|
||||
// // Suspend the keyboard interface.
|
||||
// Keyboard->suspend(true);
|
||||
//
|
||||
// // Use the base method logic.
|
||||
// KeyInterface::yield(delay);
|
||||
//
|
||||
// // Release the keyboard interface.
|
||||
// Keyboard->suspend(false);
|
||||
// } else
|
||||
// // Otherwise just delay by the required amount for timing and to give other threads a time slice.
|
||||
// {
|
||||
// KeyInterface::yield(delay);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Structure to encapsulate a single key map from PS/2 to X1.
|
||||
typedef struct {
|
||||
uint8_t ps2KeyCode;
|
||||
uint8_t ps2Ctrl;
|
||||
uint8_t keyboardModel;
|
||||
uint8_t machine;
|
||||
uint8_t x1Mode;
|
||||
uint8_t x1Key;
|
||||
uint8_t x1Key2;
|
||||
uint8_t x1Ctrl;
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[PS2TBL_X1_MAXROWS];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to maintain the X1 interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t activeKeyboardMap; // Model of keyboard a keymap entry is applicable to.
|
||||
uint8_t activeMachineModel; // Machine model a keymap entry is applicable to.
|
||||
} params;
|
||||
} t_x1Config;
|
||||
|
||||
// Configuration data.
|
||||
t_x1Config x1Config;
|
||||
|
||||
// Structure to manage the control signals signifying the state of the X1 keyboard.
|
||||
typedef struct {
|
||||
bool optionSelect; // Flag to indicate a user requested keyboard configuration option is being selected.
|
||||
bool modeB; // Mode B (Game mode) flag. If set, Mode B active, clear, Mode A active (normal keyboard).
|
||||
uint8_t keyCtrl; // Keyboard state flag control.
|
||||
|
||||
std::string fsPath; // Path on the underlying filesystem where storage is mounted and accessible.
|
||||
t_keyMapEntry *kme; // Pointer to an array in memory to contain PS2 to X1 mapping values.
|
||||
int kmeRows; // Number of rows in the kme table.
|
||||
std::string keyMapFileName; // Name of file where extension or replacement key map entries are stored.
|
||||
bool persistConfig; // Flag to request saving of the config into NVS storage.
|
||||
} t_x1Control;
|
||||
|
||||
// Transmit buffer queue item.
|
||||
typedef struct {
|
||||
uint32_t keyCode; // 32bit because normal mode A is 16bit, game mode B is 24bit
|
||||
bool modeB; // True if in game mode B.
|
||||
} t_xmitQueueMessage;
|
||||
|
||||
// Thread handles - one per function, ie. HID interface and host target interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Control structure to control interaction and mapping of keys for the host.
|
||||
t_x1Control x1Control;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE x1Mutex;
|
||||
|
||||
// Lookup table to match PS/2 codes to X1 Key and Control Data.
|
||||
//
|
||||
// Given that the X1 had many variants, with potential differences between them, the mapping table allows for ALL or variant specific entries, the first entry matching is selected.
|
||||
//
|
||||
|
||||
//
|
||||
// This mapping is for the UK Wyse KB-3926 PS/2 keyboard
|
||||
//
|
||||
t_keyMap PS2toX1 = {
|
||||
{
|
||||
// HELP
|
||||
// COPY
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'v', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // SHIFT+F1
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'w', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // SHIFT+F2
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'x', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // SHIFT+F3
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'y', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // SHIFT+F4
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'z', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // SHIFT+F5
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'q', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F1
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'r', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F2
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 's', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F3
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 't', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F4
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'u', 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F5
|
||||
{ PS2_KEY_F6, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEC, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F6
|
||||
{ PS2_KEY_F7, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEB, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F7
|
||||
{ PS2_KEY_F8, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE2, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F8
|
||||
{ PS2_KEY_F9, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE1, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // F9
|
||||
{ PS2_KEY_F10, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // XFER
|
||||
{ PS2_KEY_F11, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xFE, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // HELP
|
||||
{ PS2_KEY_F12, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // COPY
|
||||
{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x09, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // TAB
|
||||
// Control keys.
|
||||
{ PS2_KEY_APOS, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-@
|
||||
{ PS2_KEY_A, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x01, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-A
|
||||
{ PS2_KEY_B, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x02, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-B
|
||||
{ PS2_KEY_C, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x03, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-C
|
||||
{ PS2_KEY_D, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x04, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-D
|
||||
{ PS2_KEY_E, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x05, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-E
|
||||
{ PS2_KEY_F, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x06, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-F
|
||||
{ PS2_KEY_G, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x07, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-G
|
||||
{ PS2_KEY_H, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x08, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-H
|
||||
{ PS2_KEY_I, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x09, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-I
|
||||
{ PS2_KEY_J, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0A, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-J
|
||||
{ PS2_KEY_K, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0B, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-K
|
||||
{ PS2_KEY_L, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0C, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-L
|
||||
{ PS2_KEY_M, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0D, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-M
|
||||
{ PS2_KEY_N, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0E, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-N
|
||||
{ PS2_KEY_O, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0F, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-O
|
||||
{ PS2_KEY_P, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x10, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-P
|
||||
{ PS2_KEY_Q, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x11, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-Q
|
||||
{ PS2_KEY_R, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x12, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-R
|
||||
{ PS2_KEY_S, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x13, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-S
|
||||
{ PS2_KEY_T, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x14, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-T
|
||||
{ PS2_KEY_U, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x15, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-U
|
||||
{ PS2_KEY_V, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x16, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-V
|
||||
{ PS2_KEY_W, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x17, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-W
|
||||
{ PS2_KEY_X, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x18, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-X
|
||||
{ PS2_KEY_Y, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x19, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-Y
|
||||
{ PS2_KEY_Z, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1A, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-Z
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1B, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-[
|
||||
{ PS2_KEY_BACK, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1C, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-BACKSLASH
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1D, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-]
|
||||
{ PS2_KEY_6, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1E, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-^
|
||||
{ PS2_KEY_MINUS, PS2CTRL_CTRL, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1F, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CTRL-_
|
||||
// Numeric keys.
|
||||
{ PS2_KEY_0, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '0', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 0
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '1', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 1
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '2', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 2
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '3', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 3
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '4', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 4
|
||||
{ PS2_KEY_5, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '5', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 5
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '6', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 6
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '7', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 7
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '8', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 8
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '9', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // 9
|
||||
// Punctuation keys.
|
||||
{ PS2_KEY_0, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ')', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Close Right Bracket )
|
||||
{ PS2_KEY_1, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '!', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Exclamation
|
||||
{ PS2_KEY_2, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '"', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Double quote.
|
||||
{ PS2_KEY_3, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x23, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Pound Sign -> Hash
|
||||
{ PS2_KEY_4, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '$', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Dollar
|
||||
{ PS2_KEY_5, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '%', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Percent
|
||||
{ PS2_KEY_6, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '^', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Kappa
|
||||
{ PS2_KEY_7, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '&', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Ampersand
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '*', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Star
|
||||
{ PS2_KEY_9, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '(', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Open Left Bracket (
|
||||
// ALPHA keys, lower and uppercase.
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_A, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'a', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // a
|
||||
{ PS2_KEY_A, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'A', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // A
|
||||
{ PS2_KEY_B, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'b', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // b
|
||||
{ PS2_KEY_B, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'B', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // B
|
||||
{ PS2_KEY_C, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'c', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // c
|
||||
{ PS2_KEY_C, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'C', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // C
|
||||
{ PS2_KEY_D, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'd', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // d
|
||||
{ PS2_KEY_D, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'D', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // D
|
||||
{ PS2_KEY_E, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'e', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // e
|
||||
{ PS2_KEY_E, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'E', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // E
|
||||
{ PS2_KEY_F, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'f', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // f
|
||||
{ PS2_KEY_F, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'F', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // F
|
||||
{ PS2_KEY_G, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'g', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // g
|
||||
{ PS2_KEY_G, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'G', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // G
|
||||
{ PS2_KEY_H, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'h', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // h
|
||||
{ PS2_KEY_H, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'H', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // H
|
||||
{ PS2_KEY_I, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'i', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // i
|
||||
{ PS2_KEY_I, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'I', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // I
|
||||
{ PS2_KEY_J, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'j', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // j
|
||||
{ PS2_KEY_J, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'J', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // J
|
||||
{ PS2_KEY_K, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'k', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // k
|
||||
{ PS2_KEY_K, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'K', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // K
|
||||
{ PS2_KEY_L, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'l', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // l
|
||||
{ PS2_KEY_L, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'L', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // L
|
||||
{ PS2_KEY_M, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'm', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // m
|
||||
{ PS2_KEY_M, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'M', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // M
|
||||
{ PS2_KEY_N, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'n', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // n
|
||||
{ PS2_KEY_N, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'N', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // N
|
||||
{ PS2_KEY_O, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'o', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // o
|
||||
{ PS2_KEY_O, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'O', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // O
|
||||
{ PS2_KEY_P, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'p', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // p
|
||||
{ PS2_KEY_P, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'P', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // P
|
||||
{ PS2_KEY_Q, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'q', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // q
|
||||
{ PS2_KEY_Q, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'Q', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Q
|
||||
{ PS2_KEY_R, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'r', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // r
|
||||
{ PS2_KEY_R, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'R', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // R
|
||||
{ PS2_KEY_S, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 's', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // s
|
||||
{ PS2_KEY_S, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'S', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // S
|
||||
{ PS2_KEY_T, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 't', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // t
|
||||
{ PS2_KEY_T, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'T', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // T
|
||||
{ PS2_KEY_U, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'u', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // u
|
||||
{ PS2_KEY_U, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'U', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // U
|
||||
{ PS2_KEY_V, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'v', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // v
|
||||
{ PS2_KEY_V, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'V', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // V
|
||||
{ PS2_KEY_W, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'w', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // w
|
||||
{ PS2_KEY_W, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'W', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // W
|
||||
{ PS2_KEY_X, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'x', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // x
|
||||
{ PS2_KEY_X, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'X', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // X
|
||||
{ PS2_KEY_Y, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'y', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // y
|
||||
{ PS2_KEY_Y, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'Y', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Y
|
||||
{ PS2_KEY_Z, PS2CTRL_SHIFT | PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'z', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // z
|
||||
{ PS2_KEY_Z, PS2CTRL_CAPS, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 'Z', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Z
|
||||
// Mode B Mappings.
|
||||
{ PS2_KEY_Q, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b10000000, 0b00000000, 0b00000000, }, // MODE B - Q
|
||||
{ PS2_KEY_W, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b01000000, 0b00000000, 0b00000000, }, // MODE B - W
|
||||
{ PS2_KEY_E, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00100000, 0b00000000, 0b00000000, }, // MODE B - E
|
||||
{ PS2_KEY_A, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00010000, 0b00000000, 0b00000000, }, // MODE B - A
|
||||
{ PS2_KEY_D, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00001000, 0b00000000, 0b00000000, }, // MODE B - D
|
||||
{ PS2_KEY_Z, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000100, 0b00000000, 0b00000000, }, // MODE B - Z
|
||||
{ PS2_KEY_X, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000010, 0b00000000, 0b00000000, }, // MODE B - X
|
||||
{ PS2_KEY_C, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000001, 0b00000000, 0b00000000, }, // MODE B - C
|
||||
{ PS2_KEY_I, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b01000000, }, // MODE B - I - this is not 100%, the specs arent clear.
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00100000, 0b00000000, }, // MODE B - 1
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00001000, 0b00000000, }, // MODE B - 2
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000001, 0b00000000, }, // MODE B - 3
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b01000000, 0b00000000, }, // MODE B - 4
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000010, 0b00000000, }, // MODE B - 6
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b10000000, 0b00000000, }, // MODE B - 7
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00010000, 0b00000000, }, // MODE B - 8
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000100, 0b00000000, }, // MODE B - 9
|
||||
{ PS2_KEY_ESC, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b10000000, }, // MODE B - ESC
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00100000, }, // MODE B - MINUS
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00010000, }, // MODE B - PLUS
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00001000, }, // MODE B - TIMES
|
||||
{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00000100, }, // MODE B - TAB
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00000010, }, // MODE B - SPACE
|
||||
{ PS2_KEY_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00000001, }, // MODE B - RET
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00100000, 0b00000000, }, // MODE B - KeyPad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00001000, 0b00000000, }, // MODE B - KeyPad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000001, 0b00000000, }, // MODE B - KeyPad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b01000000, 0b00000000, }, // MODE B - KeyPad 4
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000010, 0b00000000, }, // MODE B - KeyPad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b10000000, 0b00000000, }, // MODE B - KeyPad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00010000, 0b00000000, }, // MODE B - KeyPad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000100, 0b00000000, }, // MODE B - KeyPad 9
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00100000, }, // MODE B - KeyPad MINUS
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00010000, }, // MODE B - KeyPad PLUS
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_B, 0b00000000, 0b00000000, 0b00001000, }, // MODE B - KeyPad TIMES
|
||||
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ' ', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Space
|
||||
{ PS2_KEY_COMMA, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '<', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Less Than <
|
||||
{ PS2_KEY_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ',', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Comma ,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ':', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Colon :
|
||||
{ PS2_KEY_SEMI, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ';', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Semi-Colon ;
|
||||
{ PS2_KEY_DOT, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '>', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Greater Than >
|
||||
{ PS2_KEY_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '.', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Full stop .
|
||||
{ PS2_KEY_DIV, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '?', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Question ?
|
||||
{ PS2_KEY_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '/', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Divide /
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '_', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Underscore
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '-', 0x00, 0xFF & ~(X1_CTRL_PRESS), },
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '@', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // At @
|
||||
{ PS2_KEY_APOS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '\'', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Single quote '
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '{', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Open Left Brace {
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '[', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Open Left Square Bracket [
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '+', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Plus +
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '=', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Equal =
|
||||
{ PS2_KEY_CAPS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ' ', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // LOCK
|
||||
{ PS2_KEY_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0D, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // ENTER/RETURN
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '}', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Close Right Brace }
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ']', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Close Right Square Bracket ]
|
||||
{ PS2_KEY_BACK, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '|', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, //
|
||||
{ PS2_KEY_BACK, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '\\', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Back slash maps to Yen
|
||||
{ PS2_KEY_BTICK, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '`', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Pipe
|
||||
{ PS2_KEY_BTICK, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '|', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Back tick `
|
||||
{ PS2_KEY_HASH, PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '~', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Tilde has no mapping.
|
||||
{ PS2_KEY_HASH, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '#', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Hash
|
||||
{ PS2_KEY_BS, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x08, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Backspace
|
||||
{ PS2_KEY_ESC, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x1B, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // ESCape
|
||||
{ PS2_KEY_SCROLL, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ' ', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Not assigned.
|
||||
{ PS2_KEY_INSERT, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_INS, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // INSERT
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_CLR, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // CLR
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_HOME, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // HOME
|
||||
{ PS2_KEY_DELETE, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_DEL, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // DELETE
|
||||
{ PS2_KEY_END, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x11, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // END
|
||||
{ PS2_KEY_PGUP, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0E, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // Roll Up.
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0F, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // Roll Down
|
||||
{ PS2_KEY_UP_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_UP, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Up Arrow
|
||||
{ PS2_KEY_L_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_LEFT, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Left Arrow
|
||||
{ PS2_KEY_DN_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_DOWN, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Down Arrow
|
||||
{ PS2_KEY_R_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, X1KEY_RIGHT, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Right Arrow
|
||||
{ PS2_KEY_NUM, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Not assigned.
|
||||
// GRPH (Alt Gr)
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_0, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xFA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+0
|
||||
{ PS2_KEY_1, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+1
|
||||
{ PS2_KEY_2, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+2
|
||||
{ PS2_KEY_3, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+3
|
||||
{ PS2_KEY_4, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+4
|
||||
{ PS2_KEY_5, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+5
|
||||
{ PS2_KEY_6, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+6
|
||||
{ PS2_KEY_7, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+7
|
||||
{ PS2_KEY_8, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+8
|
||||
{ PS2_KEY_9, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF9, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+9
|
||||
{ PS2_KEY_A, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x7F, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+A
|
||||
{ PS2_KEY_B, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x84, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+B
|
||||
{ PS2_KEY_C, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x82, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+C
|
||||
{ PS2_KEY_D, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+D
|
||||
{ PS2_KEY_E, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+E
|
||||
{ PS2_KEY_F, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEB, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+F
|
||||
{ PS2_KEY_G, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+G
|
||||
{ PS2_KEY_H, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xED, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+H
|
||||
{ PS2_KEY_I, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+I
|
||||
{ PS2_KEY_J, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+J
|
||||
{ PS2_KEY_K, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xEF, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+K
|
||||
{ PS2_KEY_L, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x8E, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+L
|
||||
{ PS2_KEY_M, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x86, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+M
|
||||
{ PS2_KEY_N, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x85, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+N
|
||||
{ PS2_KEY_O, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xF0, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+O
|
||||
{ PS2_KEY_P, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x8D, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+P
|
||||
{ PS2_KEY_Q, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE0, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+Q
|
||||
{ PS2_KEY_R, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+R
|
||||
{ PS2_KEY_S, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE9, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+S
|
||||
{ PS2_KEY_T, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+T
|
||||
{ PS2_KEY_U, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+U
|
||||
{ PS2_KEY_V, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x83, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+V
|
||||
{ PS2_KEY_W, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+W
|
||||
{ PS2_KEY_X, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x81, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+X
|
||||
{ PS2_KEY_Y, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+Y
|
||||
{ PS2_KEY_Z, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x80, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+Z
|
||||
{ PS2_KEY_COMMA, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x87, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x89, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+;
|
||||
{ PS2_KEY_DOT, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x88, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+.
|
||||
{ PS2_KEY_DIV, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xFE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+/
|
||||
{ PS2_KEY_MINUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x8C, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+-
|
||||
{ PS2_KEY_APOS, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x8A, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+'
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xFC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+[
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xE8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+]
|
||||
{ PS2_KEY_BACK, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x90, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRPH+Backslash
|
||||
{ PS2_KEY_KP0, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x8F, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x99, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x92, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x98, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x95, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x96, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x94, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x9A, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x93, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x97, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad 9
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x91, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x9D, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x9C, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x9B, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x9E, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Divide /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x90, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // GRPH+Keypad Enter /
|
||||
// KANA (Alt)
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
{ PS2_KEY_0, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+0
|
||||
{ PS2_KEY_0, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+0
|
||||
{ PS2_KEY_1, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+1
|
||||
{ PS2_KEY_2, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xCC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+2
|
||||
{ PS2_KEY_3, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+3
|
||||
{ PS2_KEY_3, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+3
|
||||
{ PS2_KEY_4, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA9, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+4
|
||||
{ PS2_KEY_4, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+4
|
||||
{ PS2_KEY_5, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+5
|
||||
{ PS2_KEY_5, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+5
|
||||
{ PS2_KEY_6, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAB, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+6
|
||||
{ PS2_KEY_6, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+6
|
||||
{ PS2_KEY_7, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+7
|
||||
{ PS2_KEY_7, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+7
|
||||
{ PS2_KEY_8, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAD, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+8
|
||||
{ PS2_KEY_8, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+8
|
||||
{ PS2_KEY_9, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+9
|
||||
{ PS2_KEY_9, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+9
|
||||
{ PS2_KEY_A, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+A
|
||||
{ PS2_KEY_B, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+B
|
||||
{ PS2_KEY_C, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBF, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+C
|
||||
{ PS2_KEY_D, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBC, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+D
|
||||
{ PS2_KEY_E, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+E
|
||||
{ PS2_KEY_E, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+E
|
||||
{ PS2_KEY_F, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xCA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+F
|
||||
{ PS2_KEY_G, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+G
|
||||
{ PS2_KEY_H, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+H
|
||||
{ PS2_KEY_I, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+I
|
||||
{ PS2_KEY_J, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xCF, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+J
|
||||
{ PS2_KEY_K, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC9, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+K
|
||||
{ PS2_KEY_L, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+L
|
||||
{ PS2_KEY_M, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+M
|
||||
{ PS2_KEY_N, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD0, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+N
|
||||
{ PS2_KEY_O, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD7, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+O
|
||||
{ PS2_KEY_P, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+P
|
||||
{ PS2_KEY_Q, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC0, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+Q
|
||||
{ PS2_KEY_R, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBD, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+R
|
||||
{ PS2_KEY_S, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+S
|
||||
{ PS2_KEY_T, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xB6, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+T
|
||||
{ PS2_KEY_U, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+U
|
||||
{ PS2_KEY_V, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xCB, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+V
|
||||
{ PS2_KEY_W, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+W
|
||||
{ PS2_KEY_X, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xBB, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+X
|
||||
{ PS2_KEY_Y, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDD, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+Y
|
||||
{ PS2_KEY_Z, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xAF, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+Z
|
||||
{ PS2_KEY_Z, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+Z
|
||||
{ PS2_KEY_COMMA, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA4, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+,
|
||||
{ PS2_KEY_COMMA, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xC8, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+,
|
||||
{ PS2_KEY_SEMI, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDA, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+;
|
||||
{ PS2_KEY_DOT, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+.
|
||||
{ PS2_KEY_DOT, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD9, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+.
|
||||
{ PS2_KEY_DIV, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA5, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+/
|
||||
{ PS2_KEY_DIV, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+/
|
||||
{ PS2_KEY_MINUS, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xCE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+-
|
||||
{ PS2_KEY_APOS, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDE, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+'
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA2, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+[
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDF, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+[
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xA3, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+]
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xD1, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+]
|
||||
{ PS2_KEY_BACK, PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0xDB, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+Backslash
|
||||
{ PS2_KEY_BS, PS2CTRL_KANA | PS2CTRL_SHIFT, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x12, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA+SHIFT+Backspace
|
||||
// Keypad.
|
||||
{ PS2_KEY_KP0, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '0', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '1', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '2', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '3', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '4', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '5', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '6', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '7', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '8', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '9', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad 9
|
||||
{ PS2_KEY_KP_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, ',', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Comma ,
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '.', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '+', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '-', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '*', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '/', 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Divide /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x0D, 0x00, 0xFF & ~(X1_CTRL_TENKEY | X1_CTRL_PRESS), }, // Keypad Enter /
|
||||
{ PS2_KEY_KP_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, '=', 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Keypad Equal =
|
||||
// ModeB Byte1 ModeB Byte2 ModeB Byte3
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X1 Keyb Mode X1 Data X1 Ctrl (Flags to Set).
|
||||
// Special keys.
|
||||
{ PS2_KEY_PRTSCR, PS2CTRL_FUNC, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // ARGO KEY
|
||||
{ PS2_KEY_PAUSE, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x03, 0x00, 0xFF & ~(X1_CTRL_PRESS | X1_CTRL_TENKEY), }, // BREAK KEY
|
||||
{ PS2_KEY_L_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // GRAPH KEY
|
||||
//{ PS2_KEY_L_ALT, PS2CTRL_FUNC | PS2CTRL_KANA, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KJ1 Sentence
|
||||
//{ PS2_KEY_R_ALT, PS2CTRL_FUNC | PS2CTRL_GRAPH, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KJ2 Transform
|
||||
{ PS2_KEY_R_GUI, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // KANA KEY
|
||||
{ PS2_KEY_MENU, PS2CTRL_FUNC | PS2CTRL_GUI, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Not assigned.
|
||||
// Modifiers are last, only being selected if an earlier match isnt made.
|
||||
{ PS2_KEY_L_SHIFT, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), },
|
||||
{ PS2_KEY_R_SHIFT, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), },
|
||||
{ PS2_KEY_L_CTRL, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), },
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), }, // Map to Control
|
||||
{ 0, PS2CTRL_NONE, KEYMAP_STANDARD, X1_ALL, X1_MODE_A, 0x00, 0x00, 0xFF & ~(X1_CTRL_PRESS), },
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // X1_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/main/include/X68K.h
|
||||
533
main/include/X68K.h
Normal file
533
main/include/X68K.h
Normal file
@@ -0,0 +1,533 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: X68K.h
|
||||
// Created: Mar 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: Header for the Sharp X68000 to PS/2 interface logic class.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2022 - Initial write.
|
||||
// v1.01 May 2022 - Initial release version.
|
||||
// v1.02 Jun 2022 - Updates to reflect changes realised in other modules due to addition of
|
||||
// bluetooth and suspend logic due to NVS issues using both cores.
|
||||
// v1.03 Jun 2022 - Further updates adding in keymaps for UK BT and Japan OADG109.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef X68K_H
|
||||
#define X68K_H
|
||||
|
||||
// Include the specification class.
|
||||
#include "KeyInterface.h"
|
||||
#include "NVS.h"
|
||||
#include "LED.h"
|
||||
#include "HID.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// NB: Macros definitions put inside class for clarity, they are still global scope.
|
||||
|
||||
// Encapsulate the Sharp X68K interface.
|
||||
class X68K : public KeyInterface {
|
||||
// Macros.
|
||||
//
|
||||
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// Constants.
|
||||
#define X68KIF_VERSION 1.03
|
||||
#define X68KIF_KEYMAP_FILE "X68K_KeyMap.BIN"
|
||||
#define MAX_X68K_XMIT_KEY_BUF 16
|
||||
#define MAX_X68K_RCV_KEY_BUF 16
|
||||
|
||||
// PS2 Flag definitions.
|
||||
#define PS2CTRL_NONE 0x00 // No keys active = 0
|
||||
#define PS2CTRL_SHIFT 0x01 // Shfit Key active = 1
|
||||
#define PS2CTRL_CTRL 0x02 // Ctrl Key active = 1
|
||||
#define PS2CTRL_CAPS 0x04 // CAPS active = 1
|
||||
#define PS2CTRL_R_CTRL 0x08 // ALT flag used as Right CTRL flag, active = 1
|
||||
#define PS2CTRL_ALTGR 0x10 // ALTGR active = 1
|
||||
#define PS2CTRL_GUI 0x20 // GUI Key active = 1
|
||||
#define PS2CTRL_FUNC 0x40 // Special Function Keys active = 1
|
||||
#define PS2CTRL_BREAK 0x80 // BREAK Key active = 1
|
||||
#define PS2CTRL_EXACT 0x80 // EXACT Match active = 1
|
||||
|
||||
// The initial mapping is made inside the PS2KeyAdvanced class from Scan Code Set 2 to ASCII
|
||||
// for a selected keyboard. Special functions are detected and combined inside this module
|
||||
// before mapping with the table below to extract the X68K key code and control data.
|
||||
// ie. PS/2 Scan Code -> ASCII + Flags -> X68K Key Code + Ctrl Data
|
||||
#define PS2TBL_X68K_MAXCOLS 6
|
||||
#define PS2TBL_X68K_MAXROWS 131
|
||||
|
||||
// Keyboard mapping table column names.
|
||||
#define PS2TBL_PS2KEYCODE_NAME "PS/2 KeyCode"
|
||||
#define PS2TBL_PS2CTRL_NAME "PS/2 Control Key"
|
||||
#define PS2TBL_KEYBOARDMODEL_NAME "For Keyboard"
|
||||
#define PS2TBL_MACHINE_NAME "For Host Model"
|
||||
#define PS2TBL_X68KKEYCODE_NAME "X68K KeyCode"
|
||||
#define PS2TBL_X68KCTRL_NAME "X68K Control Key"
|
||||
|
||||
// Keyboard mapping table column types.
|
||||
#define PS2TBL_PS2KEYCODE_TYPE "hex"
|
||||
#define PS2TBL_PS2CTRL_TYPE "custom_cbp_ps2ctrl"
|
||||
#define PS2TBL_KEYBOARDMODEL_TYPE "custom_cbp_keybmodel"
|
||||
#define PS2TBL_MACHINE_TYPE "custom_cbp_machine"
|
||||
#define PS2TBL_X68KKEYCODE_TYPE "hex"
|
||||
#define PS2TBL_X68KCTRL_TYPE "custom_cbp_x68kctrl"
|
||||
|
||||
// Keyboard mapping table select list for PS2CTRL.
|
||||
#define PS2TBL_PS2CTRL_SEL_NONE "NONE"
|
||||
#define PS2TBL_PS2CTRL_SEL_SHIFT "SHIFT"
|
||||
#define PS2TBL_PS2CTRL_SEL_CTRL "CTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_CAPS "CAPS"
|
||||
#define PS2TBL_PS2CTRL_SEL_R_CTRL "RCTRL"
|
||||
#define PS2TBL_PS2CTRL_SEL_ALTGR "ALTGR"
|
||||
#define PS2TBL_PS2CTRL_SEL_GUI "GUI"
|
||||
#define PS2TBL_PS2CTRL_SEL_FUNC "FUNC"
|
||||
#define PS2TBL_PS2CTRL_SEL_EXACT "EXACT"
|
||||
|
||||
// Keyboard mapping table select list for target machine.
|
||||
#define X68K_SEL_ALL "ALL"
|
||||
#define X68K_SEL_ORIG "ORIGINAL"
|
||||
#define X68K_SEL_ACE "ACE"
|
||||
#define X68K_SEL_EXPERT "EXPERT"
|
||||
#define X68K_SEL_PRO "PRO"
|
||||
#define X68K_SEL_SUPER "SUPER"
|
||||
#define X68K_SEL_XVI "XVI"
|
||||
#define X68K_SEL_COMPACT "COMPACT"
|
||||
#define X68K_SEL_X68030 "68030"
|
||||
|
||||
// Keyboard mapping table select list for Model of keyboard.
|
||||
#define KEYMAP_SEL_STANDARD "ALL"
|
||||
#define KEYMAP_SEL_UK_WYSE_KB3926 "UK_WYSE_KB3926"
|
||||
#define KEYMAP_SEL_JAPAN_OADG109 "JAPAN_OADG109"
|
||||
#define KEYMAP_SEL_JAPAN_SANWA_SKBL1 "JAPAN_SANWA_SKBL1"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_4 "KEYBOARD_4"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_5 "KEYBOARD_5"
|
||||
#define KEYMAP_SEL_NOT_ASSIGNED_6 "KEYBOARD_6"
|
||||
#define KEYMAP_SEL_UK_PERIBOARD_810 "UK_PERIBOARD_810"
|
||||
#define KEYMAP_SEL_UK_OMOTON_K8508 "UK_OMOTON_K8508"
|
||||
|
||||
// Keyboard mapping table select list for X68K Control codes.
|
||||
#define X68K_CTRL_SEL_NONE "NONE"
|
||||
#define X68K_CTRL_SEL_SHIFT "SHIFT"
|
||||
#define X68K_CTRL_SEL_RELEASESHIFT "RELEASESHIFT"
|
||||
#define X68K_CTRL_SEL_R_CTRL "RCTRL"
|
||||
|
||||
// X68K Key control bit mask.
|
||||
#define X68K_CTRL_SHIFT ((unsigned char) (1 << 7))
|
||||
#define X68K_CTRL_RELEASESHIFT ((unsigned char) (1 << 6))
|
||||
#define X68K_CTRL_R_CTRL ((unsigned char) (1 << 0))
|
||||
#define X68K_CTRL_NONE 0x00
|
||||
|
||||
// The Sharp X68000 Series was released over a number of years with several iterations containing changes/updates. Generally Sharp kept the X68000 compatible through the range but just in case
|
||||
// differences are found, it is possible to assign a key mapping to a specific machine type(s) or all of the series by adding the flags below into the mapping table.
|
||||
#define X68K_ALL 0xFF
|
||||
#define X68K_ORIG 0x01
|
||||
#define X68K_ACE 0x02
|
||||
#define X68K_EXPERT 0x04
|
||||
#define X68K_PRO 0x08
|
||||
#define X68K_SUPER 0x10
|
||||
#define X68K_XVI 0x20
|
||||
#define X68K_COMPACT 0x40
|
||||
#define X68K_X68030 0x80
|
||||
|
||||
// Keyboard models. The base on which this interface was created was a Wyse KB3926 PS/2 Keyboard and this is deemed STANDARD. Other models need to insert difference maps
|
||||
// prior to the STANDARD entry along with the keyboard model so that it is processed first thus allowing differing keyboards with different maps.
|
||||
#define KEYMAP_STANDARD 0xFF
|
||||
#define KEYMAP_UK_WYSE_KB3926 0x01
|
||||
#define KEYMAP_JAPAN_OADG109 0x02
|
||||
#define KEYMAP_JAPAN_SANWA_SKBL1 0x04
|
||||
#define KEYMAP_NOT_ASSIGNED_4 0x08
|
||||
#define KEYMAP_NOT_ASSIGNED_5 0x10
|
||||
#define KEYMAP_NOT_ASSIGNED_6 0x20
|
||||
#define KEYMAP_UK_PERIBOARD_810 0x40
|
||||
#define KEYMAP_UK_OMOTON_K8508 0x80
|
||||
|
||||
// X68000 Scan codes - PS2 codes along with function keys (SHIFT, CTRL etc) are mapped to the X68000 scan codes below.
|
||||
#define X68K_KEY_NULL 0x00
|
||||
#define X68K_KEY_ESC 0x01
|
||||
#define X68K_KEY_0 0x0B
|
||||
#define X68K_KEY_1 0x02
|
||||
#define X68K_KEY_2 0x03
|
||||
#define X68K_KEY_3 0x04
|
||||
#define X68K_KEY_4 0x05
|
||||
#define X68K_KEY_5 0x06
|
||||
#define X68K_KEY_6 0x07
|
||||
#define X68K_KEY_7 0x08
|
||||
#define X68K_KEY_8 0x09
|
||||
#define X68K_KEY_9 0x0A
|
||||
#define X68K_KEY_A 0x1E
|
||||
#define X68K_KEY_B 0x2E
|
||||
#define X68K_KEY_C 0x2C
|
||||
#define X68K_KEY_D 0x20
|
||||
#define X68K_KEY_E 0x13
|
||||
#define X68K_KEY_F 0x21
|
||||
#define X68K_KEY_G 0x22
|
||||
#define X68K_KEY_H 0x23
|
||||
#define X68K_KEY_I 0x18
|
||||
#define X68K_KEY_J 0x24
|
||||
#define X68K_KEY_K 0x25
|
||||
#define X68K_KEY_L 0x26
|
||||
#define X68K_KEY_M 0x30
|
||||
#define X68K_KEY_N 0x2F
|
||||
#define X68K_KEY_O 0x19
|
||||
#define X68K_KEY_P 0x1A
|
||||
#define X68K_KEY_Q 0x11
|
||||
#define X68K_KEY_R 0x14
|
||||
#define X68K_KEY_S 0x1F
|
||||
#define X68K_KEY_T 0x15
|
||||
#define X68K_KEY_U 0x17
|
||||
#define X68K_KEY_V 0x2D
|
||||
#define X68K_KEY_W 0x12
|
||||
#define X68K_KEY_X 0x2B
|
||||
#define X68K_KEY_Y 0x16
|
||||
#define X68K_KEY_Z 0x2A
|
||||
#define X68K_KEY_AT 0x1B
|
||||
#define X68K_KEY_MINUS 0x0C
|
||||
#define X68K_KEY_CIRCUMFLEX 0x0D
|
||||
#define X68K_KEY_YEN 0x0E
|
||||
#define X68K_KEY_BS 0x0F
|
||||
#define X68K_KEY_TAB 0x10
|
||||
#define X68K_KEY_OPEN_SQ 0x1C
|
||||
#define X68K_KEY_CLOSE_SQ 0x29
|
||||
#define X68K_KEY_RETURN 0x1D
|
||||
#define X68K_KEY_SEMI 0x27
|
||||
#define X68K_KEY_COLON 0x28
|
||||
#define X68K_KEY_COMMA 0x31
|
||||
#define X68K_KEY_DOT 0x32
|
||||
#define X68K_KEY_DIV 0x33
|
||||
#define X68K_KEY_UNDERLINE 0x34
|
||||
#define X68K_KEY_SPACE 0x35
|
||||
#define X68K_KEY_HOME 0x36
|
||||
#define X68K_KEY_ROLLUP 0x38
|
||||
#define X68K_KEY_ROLLDN 0x39
|
||||
#define X68K_KEY_UNDO 0x3A
|
||||
#define X68K_KEY_L_ARROW 0x3B
|
||||
#define X68K_KEY_UP_ARROW 0x3C
|
||||
#define X68K_KEY_R_ARROW 0x3D
|
||||
#define X68K_KEY_DN_ARROW 0x3E
|
||||
#define X68K_KEY_CLR 0x3F
|
||||
#define X68K_KEY_KP0 0x4F
|
||||
#define X68K_KEY_KP1 0x4B
|
||||
#define X68K_KEY_KP2 0x4C
|
||||
#define X68K_KEY_KP3 0x4D
|
||||
#define X68K_KEY_KP4 0x47
|
||||
#define X68K_KEY_KP5 0x48
|
||||
#define X68K_KEY_KP6 0x49
|
||||
#define X68K_KEY_KP7 0x43
|
||||
#define X68K_KEY_KP8 0x44
|
||||
#define X68K_KEY_KP9 0x45
|
||||
#define X68K_KEY_KP_DIV 0x40
|
||||
#define X68K_KEY_KP_TIMES 0x41
|
||||
#define X68K_KEY_KP_MINUS 0x42
|
||||
#define X68K_KEY_KP_PLUS 0x46
|
||||
#define X68K_KEY_KP_EQUAL 0x4A
|
||||
#define X68K_KEY_KP_ENTER 0x4E
|
||||
#define X68K_KEY_KP_COMMA 0x50
|
||||
#define X68K_KEY_KP_DOT 0x51
|
||||
#define X68K_KEY_SYMBOL 0x52
|
||||
#define X68K_KEY_HELP 0x54
|
||||
#define X68K_KEY_CAPS 0x5D
|
||||
#define X68K_KEY_INS 0x5E
|
||||
#define X68K_KEY_DEL 0x37
|
||||
#define X68K_KEY_BREAK 0x61
|
||||
#define X68K_KEY_COPY 0x62
|
||||
#define X68K_KEY_SHIFT 0x70
|
||||
#define X68K_KEY_CTRL 0x71
|
||||
#define X68K_KEY_XF1 0x55
|
||||
#define X68K_KEY_XF2 0x56
|
||||
#define X68K_KEY_XF3 0x57
|
||||
#define X68K_KEY_XF4 0x58
|
||||
#define X68K_KEY_XF5 0x59
|
||||
#define X68K_KEY_REGISTRATION 0x53
|
||||
#define X68K_KEY_KATAKANA 0x5A
|
||||
#define X68K_KEY_ROMAJI 0x5B
|
||||
#define X68K_KEY_TRANSPOSE 0x5C
|
||||
#define X68K_KEY_HIRAGANA 0x5F
|
||||
#define X68K_KEY_FULLWIDTH 0x60
|
||||
#define X68K_KEY_F1 0x63
|
||||
#define X68K_KEY_F2 0x64
|
||||
#define X68K_KEY_F3 0x65
|
||||
#define X68K_KEY_F4 0x66
|
||||
#define X68K_KEY_F5 0x67
|
||||
#define X68K_KEY_F6 0x68
|
||||
#define X68K_KEY_F7 0x69
|
||||
#define X68K_KEY_F8 0x6A
|
||||
#define X68K_KEY_F9 0x6B
|
||||
#define X68K_KEY_F10 0x6C
|
||||
#define X68K_KEY_OPT_1 0x72
|
||||
#define X68K_KEY_OPT_2 0x73
|
||||
|
||||
public:
|
||||
// Prototypes.
|
||||
X68K(void);
|
||||
X68K(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID, const char *fsPath);
|
||||
X68K(NVS *hdlNVS, HID *hdlHID, const char *fsPath);
|
||||
~X68K(void);
|
||||
bool createKeyMapFile(std::fstream &outFile);
|
||||
bool storeDataToKeyMapFile(std::fstream &outFile, char *data, int size);
|
||||
bool storeDataToKeyMapFile(std::fstream & outFile, std::vector<uint32_t>& dataArray);
|
||||
bool closeAndCommitKeyMapFile(std::fstream &outFile, bool cleanupOnly);
|
||||
std::string getKeyMapFileName(void) { return(X68KIF_KEYMAP_FILE); };
|
||||
void getKeyMapHeaders(std::vector<std::string>& headerList);
|
||||
void getKeyMapTypes(std::vector<std::string>& typeList);
|
||||
bool getKeyMapSelectList(std::vector<std::pair<std::string, int>>& selectList, std::string option);
|
||||
bool getKeyMapData(std::vector<uint32_t>& dataArray, int *row, bool start);
|
||||
|
||||
// Method to return the class version number.
|
||||
float version(void)
|
||||
{
|
||||
return(X68KIF_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Prototypes.
|
||||
IRAM_ATTR void pushKeyToQueue(uint32_t key);
|
||||
IRAM_ATTR void pushHostCmdToQueue(uint8_t cmd);
|
||||
IRAM_ATTR static void x68kInterface( void * pvParameters );
|
||||
IRAM_ATTR static void hidInterface( void * pvParameters );
|
||||
void selectOption(uint8_t optionCode);
|
||||
uint32_t mapKey(uint16_t scanCode);
|
||||
bool loadKeyMap();
|
||||
bool saveKeyMap(void);
|
||||
void init(uint32_t ifMode, NVS *hdlNVS, LED *hdlLED, HID *hdlHID);
|
||||
void init(NVS *hdlNVS, HID *hdlHID);
|
||||
|
||||
// Structure to encapsulate a single key map from PS/2 to X68K.
|
||||
typedef struct {
|
||||
uint8_t ps2KeyCode;
|
||||
uint8_t ps2Ctrl;
|
||||
uint8_t keyboardModel;
|
||||
uint8_t machine;
|
||||
uint8_t x68kKey;
|
||||
uint8_t x68kCtrl;
|
||||
} t_keyMapEntry;
|
||||
|
||||
// Structure to encapsulate the entire static keyboard mapping table.
|
||||
typedef struct {
|
||||
t_keyMapEntry kme[PS2TBL_X68K_MAXROWS];
|
||||
} t_keyMap;
|
||||
|
||||
// Structure to maintain the X68000 interface configuration data. This data is persisted through powercycles as needed.
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t activeKeyboardMap; // Model of keyboard a keymap entry is applicable to.
|
||||
uint8_t activeMachineModel; // Machine model a keymap entry is applicable to.
|
||||
bool useOnlyPersisted; // Flag to indicate wether the inbuilt keymap array should be combined with persisted values or the inbuilt array is ignored and only persisted values used.
|
||||
} params;
|
||||
} t_x68kConfig;
|
||||
|
||||
// Configuration data.
|
||||
t_x68kConfig x68kConfig;
|
||||
|
||||
// Structure to manage the control signals signifying the state of the X68K keyboard.
|
||||
typedef struct {
|
||||
uint8_t keyCtrl; // Keyboard state flag control.
|
||||
bool optionSelect; // Flag to indicate a user requested keyboard configuration option is being selected.
|
||||
int uartNum;
|
||||
int uartBufferSize;
|
||||
int uartQueueSize;
|
||||
|
||||
std::string fsPath; // Path on the underlying filesystem where storage is mounted and accessible.
|
||||
t_keyMapEntry *kme; // Pointer to an array in memory to contain PS2 to X68K mapping values.
|
||||
int kmeRows; // Number of rows in the kme table.
|
||||
std::string keyMapFileName; // Name of file where extension or replacement key map entries are stored.
|
||||
bool persistConfig; // Flag to request saving of the config into NVS storage.
|
||||
} t_x68kControl;
|
||||
|
||||
// Transmit buffer queue item.
|
||||
typedef struct {
|
||||
uint32_t keyCode; // Key data to be sent to X68000.
|
||||
} t_xmitQueueMessage;
|
||||
|
||||
// Receive buffer queue item.
|
||||
typedef struct {
|
||||
uint8_t hostCmd; // Keyboard configuration command received from X68000.
|
||||
} t_rcvQueueMessage;
|
||||
|
||||
// Thread handles - one per function, ie. HID interface and host target interface.
|
||||
TaskHandle_t TaskHostIF = NULL;
|
||||
TaskHandle_t TaskHIDIF = NULL;
|
||||
|
||||
// Control structure to control interaction and mapping of keys for the host.
|
||||
t_x68kControl x68kControl;
|
||||
|
||||
// Spin lock mutex to hold a coresied to an uninterruptable method. This only works on dual core ESP32's.
|
||||
portMUX_TYPE x68kMutex;
|
||||
|
||||
// Lookup table to match PS/2 codes to X68K Key and Control Data.
|
||||
//
|
||||
// Given that the X68K had many variants, with potential differences between them, the mapping table allows for ALL or variant specific entries, the first entry matching is selected.
|
||||
//
|
||||
// This mapping is for the UK Wyse KB-3926 PS/2 keyboard which is deemed the KEYMAP_STANDARD and all other variants need to add additional mappings below, position sensitive, ie. add non-standard entries before standard entry.
|
||||
//
|
||||
//const unsigned char PS2toX68K[PS2TBL_X68K_MAXROWS][PS2TBL_X68K_MAXCOLS] =
|
||||
//t_keyMapEntry PS2toX68K[PS2TBL_X68K_MAXROWS] =
|
||||
t_keyMap PS2toX68K = {
|
||||
{
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Keyboard Model Machine X68K Data X68K Ctrl (Flags to Set).
|
||||
// Function keys
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_HIRAGANA, X68K_CTRL_NONE, }, // R_CTRL + F1 = Hiragana
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_FULLWIDTH, X68K_CTRL_NONE, }, // R_CTRL + F2 = Full Width
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KATAKANA, X68K_CTRL_NONE, }, // R_CTRL + F3 = Katakana
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_ROMAJI, X68K_CTRL_NONE, }, // R_CTRL + F4 = Romaji
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_TRANSPOSE, X68K_CTRL_NONE, }, // R_CTRL + F5 = Tranpose
|
||||
{ PS2_KEY_F6, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SYMBOL, X68K_CTRL_NONE, }, // R_CTRL + F6 = Symbol
|
||||
{ PS2_KEY_F7, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_REGISTRATION, X68K_CTRL_NONE, }, // R_CTRL + F7 = Registration - maybe a poor translation, needs better one!
|
||||
{ PS2_KEY_F9, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_COPY, X68K_CTRL_NONE, }, // R_CTRL + F9 = Copy
|
||||
{ PS2_KEY_F10, PS2CTRL_FUNC | PS2CTRL_CTRL | PS2CTRL_R_CTRL, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_HELP, X68K_CTRL_NONE, }, // R_CTRL + F10 = Help
|
||||
{ PS2_KEY_F1, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F1, X68K_CTRL_NONE, }, // F1
|
||||
{ PS2_KEY_F2, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F2, X68K_CTRL_NONE, }, // F2
|
||||
{ PS2_KEY_F3, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F3, X68K_CTRL_NONE, }, // F3
|
||||
{ PS2_KEY_F4, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F4, X68K_CTRL_NONE, }, // F4
|
||||
{ PS2_KEY_F5, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F5, X68K_CTRL_NONE, }, // F5
|
||||
{ PS2_KEY_F6, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F6, X68K_CTRL_NONE, }, // F6
|
||||
{ PS2_KEY_F7, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F7, X68K_CTRL_NONE, }, // F7
|
||||
{ PS2_KEY_F8, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F8, X68K_CTRL_NONE, }, // F8
|
||||
{ PS2_KEY_F9, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F9, X68K_CTRL_NONE, }, // F9
|
||||
{ PS2_KEY_F10, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F10, X68K_CTRL_NONE, }, // F10
|
||||
{ PS2_KEY_F11, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_OPT_1, X68K_CTRL_NONE, }, // F11 - OPT.1
|
||||
{ PS2_KEY_F12, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_OPT_2, X68K_CTRL_NONE, }, // F12 - OPT.2
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X68K Data X68K Ctrl (Flags to Set).
|
||||
// ALPHA keys, case is maaped in the X68000 via the SHIFT key event or CAPS key.
|
||||
{ PS2_KEY_A, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_A, X68K_CTRL_NONE, }, // A
|
||||
{ PS2_KEY_B, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_B, X68K_CTRL_NONE, }, // B
|
||||
{ PS2_KEY_C, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_C, X68K_CTRL_NONE, }, // C
|
||||
{ PS2_KEY_D, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_D, X68K_CTRL_NONE, }, // D
|
||||
{ PS2_KEY_E, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_E, X68K_CTRL_NONE, }, // E
|
||||
{ PS2_KEY_F, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_F, X68K_CTRL_NONE, }, // F
|
||||
{ PS2_KEY_G, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_G, X68K_CTRL_NONE, }, // G
|
||||
{ PS2_KEY_H, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_H, X68K_CTRL_NONE, }, // H
|
||||
{ PS2_KEY_I, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_I, X68K_CTRL_NONE, }, // I
|
||||
{ PS2_KEY_J, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_J, X68K_CTRL_NONE, }, // J
|
||||
{ PS2_KEY_K, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_K, X68K_CTRL_NONE, }, // K
|
||||
{ PS2_KEY_L, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_L, X68K_CTRL_NONE, }, // L
|
||||
{ PS2_KEY_M, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_M, X68K_CTRL_NONE, }, // M
|
||||
{ PS2_KEY_N, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_N, X68K_CTRL_NONE, }, // N
|
||||
{ PS2_KEY_O, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_O, X68K_CTRL_NONE, }, // O
|
||||
{ PS2_KEY_P, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_P, X68K_CTRL_NONE, }, // P
|
||||
{ PS2_KEY_Q, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_Q, X68K_CTRL_NONE, }, // Q
|
||||
{ PS2_KEY_R, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_R, X68K_CTRL_NONE, }, // R
|
||||
{ PS2_KEY_S, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_S, X68K_CTRL_NONE, }, // S
|
||||
{ PS2_KEY_T, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_T, X68K_CTRL_NONE, }, // T
|
||||
{ PS2_KEY_U, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_U, X68K_CTRL_NONE, }, // U
|
||||
{ PS2_KEY_V, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_V, X68K_CTRL_NONE, }, // V
|
||||
{ PS2_KEY_W, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_W, X68K_CTRL_NONE, }, // W
|
||||
{ PS2_KEY_X, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_X, X68K_CTRL_NONE, }, // X
|
||||
{ PS2_KEY_Y, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_Y, X68K_CTRL_NONE, }, // Y
|
||||
{ PS2_KEY_Z, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_Z, X68K_CTRL_NONE, }, // Z
|
||||
// Numeric keys.
|
||||
{ PS2_KEY_0, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_9, X68K_CTRL_NONE, }, // Close Bracket )
|
||||
{ PS2_KEY_0, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_0, X68K_CTRL_NONE, }, // 0
|
||||
{ PS2_KEY_1, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_1, X68K_CTRL_NONE, }, // 1
|
||||
{ PS2_KEY_2, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_2, X68K_CTRL_NONE, }, // 2
|
||||
{ PS2_KEY_3, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_3, X68K_CTRL_NONE, }, // 3
|
||||
{ PS2_KEY_4, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_4, X68K_CTRL_NONE, }, // 4
|
||||
{ PS2_KEY_5, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_5, X68K_CTRL_NONE, }, // 5
|
||||
{ PS2_KEY_6, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CIRCUMFLEX, X68K_CTRL_RELEASESHIFT, }, // Circumflex ^
|
||||
{ PS2_KEY_6, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_6, X68K_CTRL_NONE, }, // 6
|
||||
{ PS2_KEY_7, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_6, X68K_CTRL_NONE, }, // &
|
||||
{ PS2_KEY_7, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_7, X68K_CTRL_NONE, }, // 7
|
||||
{ PS2_KEY_8, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_COLON, X68K_CTRL_NONE, }, // Start *
|
||||
{ PS2_KEY_8, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_8, X68K_CTRL_NONE, }, // 8
|
||||
{ PS2_KEY_9, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_8, X68K_CTRL_NONE, }, // Open Bracket (
|
||||
{ PS2_KEY_9, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_9, X68K_CTRL_NONE, }, // 9
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X68K Data X68K Ctrl (Flags to Set).
|
||||
// Punctuation keys.
|
||||
{ PS2_KEY_SPACE, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SPACE, X68K_CTRL_NONE, }, // Space
|
||||
{ PS2_KEY_MINUS, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CIRCUMFLEX, X68K_CTRL_NONE, }, // Upper Bar
|
||||
{ PS2_KEY_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_MINUS, X68K_CTRL_NONE, }, // Minus -
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SEMI, X68K_CTRL_SHIFT, }, // Plus +
|
||||
{ PS2_KEY_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_MINUS, X68K_CTRL_SHIFT, }, // Equal =
|
||||
{ PS2_KEY_DOT, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_DOT, X68K_CTRL_NONE, }, // Greater Than >
|
||||
{ PS2_KEY_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_DOT, X68K_CTRL_NONE, }, // Dot
|
||||
{ PS2_KEY_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_DIV, X68K_CTRL_NONE, }, // Divide /
|
||||
{ PS2_KEY_SEMI, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_COLON, X68K_CTRL_RELEASESHIFT, }, // Colon :
|
||||
{ PS2_KEY_SEMI, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SEMI, X68K_CTRL_NONE, }, // Semi-Colon ;
|
||||
{ PS2_KEY_OPEN_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_OPEN_SQ, X68K_CTRL_NONE, }, // [
|
||||
{ PS2_KEY_CLOSE_SQ, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CLOSE_SQ, X68K_CTRL_NONE, }, // ]
|
||||
{ PS2_KEY_APOS, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_AT, X68K_CTRL_RELEASESHIFT, }, // @
|
||||
{ PS2_KEY_APOS, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_7, X68K_CTRL_SHIFT, }, // '
|
||||
{ PS2_KEY_BACK, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_YEN, X68K_CTRL_NONE, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_BACK, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_YEN, X68K_CTRL_NONE, }, // Back slash maps to Yen
|
||||
{ PS2_KEY_HASH, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_3, X68K_CTRL_SHIFT, }, // Hash
|
||||
{ PS2_KEY_COMMA, PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_COMMA, X68K_CTRL_NONE, }, // Less Than <
|
||||
{ PS2_KEY_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_COMMA, X68K_CTRL_NONE, }, // Comma ,
|
||||
{ PS2_KEY_BTICK, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_UNDERLINE, X68K_CTRL_SHIFT, }, // Underline
|
||||
{ PS2_KEY_BTICK, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_AT, X68K_CTRL_SHIFT, }, // Back Tick `
|
||||
// Control keys.
|
||||
{ PS2_KEY_TAB, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_TAB, X68K_CTRL_NONE, }, // TAB
|
||||
{ PS2_KEY_BS, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_BS, X68K_CTRL_NONE, }, // Backspace
|
||||
{ PS2_KEY_ESC, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_ESC, X68K_CTRL_NONE, }, // ESCape
|
||||
{ PS2_KEY_INSERT, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_INS, X68K_CTRL_NONE, }, // INSERT
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CLR, X68K_CTRL_NONE, }, // CLR
|
||||
{ PS2_KEY_HOME, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_HOME, X68K_CTRL_NONE, }, // HOME
|
||||
{ PS2_KEY_DELETE, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_DEL, X68K_CTRL_NONE, }, // DELETE
|
||||
{ PS2_KEY_UP_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_UP_ARROW, X68K_CTRL_NONE, }, // Up Arrow
|
||||
{ PS2_KEY_L_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_L_ARROW, X68K_CTRL_NONE, }, // Left Arrow
|
||||
{ PS2_KEY_DN_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_DN_ARROW, X68K_CTRL_NONE, }, // Down Arrow
|
||||
{ PS2_KEY_R_ARROW, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_R_ARROW, X68K_CTRL_NONE, }, // Right Arrow
|
||||
{ PS2_KEY_PGUP, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_ROLLUP, X68K_CTRL_NONE, }, // Roll Up.
|
||||
{ PS2_KEY_PGDN, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_ROLLDN, X68K_CTRL_NONE, }, // Roll Down
|
||||
{ PS2_KEY_SCROLL, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, ' ', X68K_CTRL_NONE, }, // Not assigned.
|
||||
{ PS2_KEY_ENTER, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_RETURN, X68K_CTRL_NONE, }, // Not assigned.
|
||||
{ PS2_KEY_CAPS, PS2CTRL_CAPS, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CAPS, X68K_CTRL_NONE, }, // CAPS
|
||||
{ PS2_KEY_END, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_UNDO, X68K_CTRL_NONE, }, // UNDO
|
||||
// Keypad.
|
||||
{ PS2_KEY_KP0, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP0, X68K_CTRL_NONE, }, // Keypad 0
|
||||
{ PS2_KEY_KP1, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP1, X68K_CTRL_NONE, }, // Keypad 1
|
||||
{ PS2_KEY_KP2, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP2, X68K_CTRL_NONE, }, // Keypad 2
|
||||
{ PS2_KEY_KP3, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP3, X68K_CTRL_NONE, }, // Keypad 3
|
||||
{ PS2_KEY_KP4, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP4, X68K_CTRL_NONE, }, // Keypad 4
|
||||
{ PS2_KEY_KP5, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP5, X68K_CTRL_NONE, }, // Keypad 5
|
||||
{ PS2_KEY_KP6, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP6, X68K_CTRL_NONE, }, // Keypad 6
|
||||
{ PS2_KEY_KP7, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP7, X68K_CTRL_NONE, }, // Keypad 7
|
||||
{ PS2_KEY_KP8, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP8, X68K_CTRL_NONE, }, // Keypad 8
|
||||
{ PS2_KEY_KP9, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP9, X68K_CTRL_NONE, }, // Keypad 9
|
||||
{ PS2_KEY_KP_COMMA, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_COMMA, X68K_CTRL_NONE, }, // Keypad Comma ,
|
||||
{ PS2_KEY_KP_DOT, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_DOT, X68K_CTRL_NONE, }, // Keypad Full stop .
|
||||
{ PS2_KEY_KP_PLUS, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_PLUS, X68K_CTRL_NONE, }, // Keypad Plus +
|
||||
{ PS2_KEY_KP_MINUS, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_MINUS, X68K_CTRL_NONE, }, // Keypad Minus -
|
||||
{ PS2_KEY_KP_TIMES, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_TIMES, X68K_CTRL_NONE, }, // Keypad Times *
|
||||
{ PS2_KEY_KP_DIV, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_DIV, X68K_CTRL_NONE, }, // Keypad Divide /
|
||||
{ PS2_KEY_KP_EQUAL, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_MINUS, X68K_CTRL_SHIFT, }, // Keypad Equal =
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_ENTER, X68K_CTRL_NONE, }, // Keypad Ebter /
|
||||
{ PS2_KEY_KP_ENTER, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_KP_EQUAL, X68K_CTRL_NONE, }, // Keypad Ebter /
|
||||
//PS2 Code PS2 Ctrl (Flags to Match) Machine X68K Data X68K Ctrl (Flags to Set).
|
||||
// Special keys.
|
||||
{ PS2_KEY_PRTSCR, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, 0x00, X68K_CTRL_NONE, }, //
|
||||
{ PS2_KEY_PAUSE, PS2CTRL_FUNC | PS2CTRL_SHIFT, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_BREAK, X68K_CTRL_RELEASESHIFT, }, // BREAK KEY
|
||||
{ PS2_KEY_L_GUI, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_XF1, X68K_CTRL_NONE, }, // XF1
|
||||
{ PS2_KEY_L_ALT, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_XF2, X68K_CTRL_NONE, }, // XF2
|
||||
{ PS2_KEY_R_ALT, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_XF3, X68K_CTRL_NONE, }, // XF3
|
||||
{ PS2_KEY_R_GUI, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_XF4, X68K_CTRL_NONE, }, // XF4
|
||||
{ PS2_KEY_MENU, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_XF5, X68K_CTRL_NONE, }, // XF5
|
||||
// Modifiers are last, only being selected if an earlier match isnt made.
|
||||
{ PS2_KEY_L_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SHIFT, X68K_CTRL_NONE, }, //
|
||||
{ PS2_KEY_R_SHIFT, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_SHIFT, X68K_CTRL_NONE, }, //
|
||||
{ PS2_KEY_L_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CTRL, X68K_CTRL_NONE, }, // Map to Control
|
||||
{ PS2_KEY_R_CTRL, PS2CTRL_FUNC, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_CTRL, X68K_CTRL_NONE, }, // Map to Control
|
||||
{ 0, PS2CTRL_NONE, KEYMAP_STANDARD, X68K_ALL, X68K_KEY_NULL, X68K_CTRL_NONE, }, //
|
||||
}};
|
||||
};
|
||||
|
||||
#endif // X68K_H
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/bootstrap.min.css.gz
|
||||
BIN
webserver/css/bootstrap.min.css.gz
Normal file
BIN
webserver/css/bootstrap.min.css.gz
Normal file
Binary file not shown.
1
webserver/css/jquery.edittable.min.css
vendored
1
webserver/css/jquery.edittable.min.css
vendored
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/jquery.edittable.min.css
|
||||
18
webserver/css/jquery.edittable.min.css
vendored
Normal file
18
webserver/css/jquery.edittable.min.css
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
table.inputtable{width:100%;border:1px solid #ddd;border-collapse:collapse;border-spacing:0;-moz-box-shadow:0 1px 3px rgba(0,0,0,.075);-webkit-box-shadow:0 1px 3px rgba(0,0,0,.075);box-shadow:0 1px 3px rgba(0,0,0,.075);margin:15px 0}
|
||||
table.inputtable a.icon-button{background-color:#ccc;display:inline-block;width:18px;height:18px;text-decoration:none;color:#fff;font-weight:800;line-height:16px;text-align:center;font-size:14px;-moz-border-radius:1px;-webkit-border-radius:1px;border-radius:1px;-moz-box-shadow:0 0 1px rgba(0,0,0,0.2);-webkit-box-shadow:0 0 1px rgba(0,0,0,0.2);box-shadow:0 0 1px rgba(0,0,0,0.2)}
|
||||
table.inputtable a.icon-button.addcol,table.inputtable a.icon-button.addrow{background-color:#81b71a}
|
||||
table.inputtable a.icon-button.delcol,table.inputtable a.icon-button.delrow{background-color:#db4a39}
|
||||
table.inputtable a.icon-button.disabled{background-color:#eee}
|
||||
table.inputtable td:last-child,table.inputtable th:last-child{width:54px;border:1px solid #eee;border-right:thick;}
|
||||
table.inputtable td,table.inputtable th{border:1px solid #eee;text-align:center;height:40px;vertical-align:middle;font-size:14px}
|
||||
table.inputtable th{background-color:#f1f1f1;border-top:none;border-bottom:2px solid #ddd;border-color:#ddd}
|
||||
table.inputtable td input[type=text]{border:0;width:90%;height:100%;text-align:center;padding:0 5%}
|
||||
table.inputtable tr td input:focus{background-color:#fafafa}
|
||||
table.inputtable.wh tbody tr:nth-child(1),table.inputtable.wh tbody tr:nth-child(1) input{background-color:#fdfdfd;font-weight:800}
|
||||
table.inputtable th:first-child,table.inputtable td:first-child{border-left:none}
|
||||
table.inputtable tr:last-child td{border-bottom:none}
|
||||
@media only screen and max-width 480px {
|
||||
table.inputtable td,table.inputtable th{min-width:40px;height:80px}
|
||||
table.inputtable a.icon-button{width:40px;height:40px;font-size:18px;min-width:40px;line-height:40px;margin:3px 0}
|
||||
table.inputtable td input{height:80px}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/sb-admin.css
|
||||
159
webserver/css/sb-admin.css
Normal file
159
webserver/css/sb-admin.css
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
Author: Start Bootstrap - http://startbootstrap.com
|
||||
'SB Admin' HTML Template by Start Bootstrap
|
||||
|
||||
All Start Bootstrap themes are licensed under Apache 2.0.
|
||||
For more info and more free Bootstrap 3 HTML themes, visit http://startbootstrap.com!
|
||||
*/
|
||||
|
||||
/* ATTN: This is mobile first CSS - to update 786px and up screen width use the media query near the bottom of the document! */
|
||||
|
||||
/* Global Styles */
|
||||
|
||||
body {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#page-wrapper {
|
||||
width: 100%;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
/* Nav Messages */
|
||||
|
||||
.messages-dropdown .dropdown-menu .message-preview .avatar,
|
||||
.messages-dropdown .dropdown-menu .message-preview .name,
|
||||
.messages-dropdown .dropdown-menu .message-preview .message,
|
||||
.messages-dropdown .dropdown-menu .message-preview .time {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.messages-dropdown .dropdown-menu .message-preview .avatar {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.messages-dropdown .dropdown-menu .message-preview .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.messages-dropdown .dropdown-menu .message-preview .message {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.messages-dropdown .dropdown-menu .message-preview .time {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
/* Nav Announcements */
|
||||
|
||||
.announcement-heading {
|
||||
font-size: 50px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.announcement-text {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Table Headers */
|
||||
|
||||
table.tablesorter thead {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.tablesorter thead tr th:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* Flot Chart Containers */
|
||||
|
||||
.flot-chart {
|
||||
display: block;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.flot-chart-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Edit Below to Customize Widths > 768px */
|
||||
@media (min-width:768px) {
|
||||
|
||||
/* Wrappers */
|
||||
|
||||
#wrapper {
|
||||
padding-left: 225px;
|
||||
}
|
||||
|
||||
#page-wrapper {
|
||||
padding: 15px 25px;
|
||||
}
|
||||
|
||||
/* Side Nav */
|
||||
|
||||
.side-nav {
|
||||
margin-left: -225px;
|
||||
left: 225px;
|
||||
width: 225px;
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
background-color: #222222;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Bootstrap Default Overrides - Customized Dropdowns for the Side Nav */
|
||||
|
||||
.side-nav>li.dropdown>ul.dropdown-menu {
|
||||
position: relative;
|
||||
min-width: 225px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
}
|
||||
|
||||
.side-nav>li.dropdown>ul.dropdown-menu>li>a {
|
||||
color: #999999;
|
||||
padding: 15px 15px 15px 25px;
|
||||
}
|
||||
|
||||
.side-nav>li.dropdown>ul.dropdown-menu>li>a:hover,
|
||||
.side-nav>li.dropdown>ul.dropdown-menu>li>a.active,
|
||||
.side-nav>li.dropdown>ul.dropdown-menu>li>a:focus {
|
||||
color: #fff;
|
||||
background-color: #080808;
|
||||
}
|
||||
|
||||
.side-nav>li>a {
|
||||
width: 225px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>li>a:hover,
|
||||
.navbar-inverse .navbar-nav>li>a:focus {
|
||||
background-color: #080808;
|
||||
}
|
||||
|
||||
/* Nav Messages */
|
||||
|
||||
.messages-dropdown .dropdown-menu {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.messages-dropdown .dropdown-menu li a {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/sharpkey.css
|
||||
266
webserver/css/sharpkey.css
Normal file
266
webserver/css/sharpkey.css
Normal file
@@ -0,0 +1,266 @@
|
||||
.wm-button {
|
||||
width: 95px;
|
||||
height: 25px;
|
||||
background: blue;
|
||||
border: none;
|
||||
vertical-align: top;
|
||||
margin-left: 25px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
transition: 2s;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.wm-button:disabled {
|
||||
background: #999;
|
||||
color: #555;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.wm-button:hover {
|
||||
background-color: #81ecec;
|
||||
border: 2px solid #00cec9;
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.firmware-file-upload {
|
||||
width: 95px;
|
||||
height: 25px;
|
||||
background: blue;
|
||||
border: none;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
line-height: 25px;
|
||||
margin-left: 35px;
|
||||
margin-bottom: 0px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
transition: 2s;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.firmware-file-upload:hover {
|
||||
background-color: #81ecec;
|
||||
border: 2px solid #00cec9;
|
||||
}
|
||||
|
||||
|
||||
.keymap-file-upload {
|
||||
width: 95px;
|
||||
height: 25px;
|
||||
background: blue;
|
||||
border: none;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
line-height: 25px;
|
||||
margin-left: 35px;
|
||||
margin-bottom: 0px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
transition: 2s;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.keymap-file-upload:hover {
|
||||
background-color: #81ecec;
|
||||
border: 2px solid #00cec9;
|
||||
}
|
||||
|
||||
input[type=file]::file-selector-button {
|
||||
border: 2px solid #6c5ce7;
|
||||
padding: .2em .4em;
|
||||
border-radius: .2em;
|
||||
background-color: #a29bfe;
|
||||
transition: 1s;
|
||||
}
|
||||
|
||||
input[type=file]::file-selector-button:hover {
|
||||
background-color: #81ecec;
|
||||
border: 2px solid #00cec9;
|
||||
}
|
||||
|
||||
.sk-modules-table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.sk-modules-table caption {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
.sk-modules-table th, .sk-modules-table td {
|
||||
border: none;
|
||||
padding: 0.2rem 2rem;
|
||||
}
|
||||
.sk-modules-table td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.sk-modules-table th {
|
||||
font-weight: normal;
|
||||
}
|
||||
.sk-modules-table td {
|
||||
border-style: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
.sk-modules-table th {
|
||||
padding: 0.2em;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sk-modules-table tbody td:first-child::after {
|
||||
content: leader(". ");
|
||||
}
|
||||
|
||||
.sk-client-wifi-config-table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
width: 1px !important;
|
||||
table-layout: auto !important;
|
||||
}
|
||||
.sk-client-wifi-config-table caption {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
.sk-client-wifi-config-table th, .sk-client-wifi-config-table td {
|
||||
border: none;
|
||||
padding: 0.2rem 2rem;
|
||||
padding-left: 0;
|
||||
padding-right: 4rem;
|
||||
}
|
||||
.sk-client-wifi-config-table td {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border-style: none;
|
||||
vertical-align: top;
|
||||
width: auto !important;
|
||||
}
|
||||
.sk-client-wifi-config-table th {
|
||||
font-weight: normal;
|
||||
padding: 0.2em;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
#client-wifi-config-area {
|
||||
overflow-x: scroll;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#firmware-revision-area {
|
||||
overflow-x: scroll;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#esp32-partitions-area {
|
||||
overflow-x: scroll;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.sk-partitions-table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.sk-partitions-table caption {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
.sk-partitions-table th, .sk-partitions-table td {
|
||||
border: none;
|
||||
padding: 0.2rem 2rem;
|
||||
}
|
||||
.sk-partitions-table td {
|
||||
white-space: nowrap;
|
||||
border-style: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
.sk-partitions-table th {
|
||||
font-weight: normal;
|
||||
padding: 0.2em;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sk-partitions-table tbody td:first-child::after {
|
||||
content: leader(". ");
|
||||
}
|
||||
|
||||
.sk-partitions-table tbody td:nth-child(4) {
|
||||
text-align: right;
|
||||
}
|
||||
.sk-partitions-table tbody td:nth-child(5) {
|
||||
text-align: right;
|
||||
}
|
||||
.sk-partitions-table tbody td:nth-child(6) {
|
||||
text-align: center;
|
||||
}
|
||||
.sk-partitions-table tbody td:nth-child(8) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-condensed .progress {
|
||||
margin-bottom: 0 !important;
|
||||
width: 400px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.table-borderless > tbody > tr > td,
|
||||
.table-borderless > thead > tr > td,
|
||||
.table-borderless {
|
||||
border-bottom: 0;
|
||||
border-top: 0;
|
||||
padding: 4px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
border-bottom: 0;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
padding: 4px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 0;
|
||||
white-space: nowrap;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.justify {
|
||||
text-align: justify;
|
||||
text-justify: inter-word;
|
||||
}
|
||||
|
||||
.keymap {
|
||||
max-height: 36.2em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.hr_no_margin {
|
||||
margin-top: 0.2em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
overflow: hidden;
|
||||
}
|
||||
.radio-mouse {
|
||||
padding-right: 1em;
|
||||
}
|
||||
.radio-mouse label {
|
||||
float: left;
|
||||
clear: none;
|
||||
display: block;
|
||||
padding: 0px 1em 0px 8px;
|
||||
}
|
||||
input[type=radio] .radio-mouse,
|
||||
input.radio .radio-mouse {
|
||||
float: left;
|
||||
clear: none;
|
||||
margin: 2px 0 0 2px;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/style.css
|
||||
253
webserver/css/style.css
Normal file
253
webserver/css/style.css
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
color: #06D85F;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
*/
|
||||
.box {
|
||||
width: 40%;
|
||||
margin: 0 auto;
|
||||
background: rgba(255,255,255,0.2);
|
||||
padding: 35px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 20px/50px;
|
||||
background-clip: padding-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
//transition: opacity 500ms;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.overlay:target {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.popup {
|
||||
margin: 70px auto;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
width: 30%;
|
||||
position: relative;
|
||||
transition: all 5s ease-in-out;
|
||||
}
|
||||
|
||||
.popup h2 {
|
||||
margin-top: 0;
|
||||
color: #333;
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
}
|
||||
.popup .close {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 30px;
|
||||
transition: all 200ms;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
.popup .close:hover {
|
||||
color: #06D85F;
|
||||
}
|
||||
.popup .content {
|
||||
max-height: 30%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px){
|
||||
.box{
|
||||
width: 90%;
|
||||
}
|
||||
.popup{
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
html {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.8rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
*/
|
||||
|
||||
.topnav {
|
||||
overflow: hidden;
|
||||
background-color: #0A1128;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 5%;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-gap: 2rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: lightyellow;
|
||||
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: #034078
|
||||
}
|
||||
/*
|
||||
input[type=submit] {
|
||||
border: none;
|
||||
color: #FEFCFB;
|
||||
background-color: #034078;
|
||||
padding: 15px 15px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 18px;
|
||||
width: 30%;
|
||||
margin-right: 10px;
|
||||
border-radius: 4px;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
|
||||
input[type=submit]:hover {
|
||||
background-color: #1282A2;
|
||||
}
|
||||
|
||||
input[type=text], input[type=number], select {
|
||||
width: 40%;
|
||||
padding: 8px 10px;
|
||||
margin: 12px;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type=url], input[type=number], select {
|
||||
width: 50%;
|
||||
padding: 12px 20px;
|
||||
margin: 18px;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
*/
|
||||
.value{
|
||||
font-size: 1rem;
|
||||
color: #1282A2;
|
||||
}
|
||||
.state {
|
||||
font-size: 1rem;
|
||||
color: #1282A2;
|
||||
}
|
||||
|
||||
.button {
|
||||
font-size: 2em;
|
||||
padding: 3px;
|
||||
color: #dbd75e;
|
||||
border: 1px solid #000;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all 1s ease-out;
|
||||
|
||||
background: #1b06d8;
|
||||
}
|
||||
.button:hover {
|
||||
background: #06D85F;
|
||||
}
|
||||
|
||||
/*
|
||||
button {
|
||||
//border: none;
|
||||
// color: #FEFCFB;
|
||||
// padding: 15px 32px;
|
||||
// text-align: center;
|
||||
// font-size: 30px;
|
||||
// width: 100px;
|
||||
// border-radius: 4px;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
.button-on {
|
||||
// background-color: #034078;
|
||||
}
|
||||
.button-on:hover {
|
||||
// background-color: #1282A2;
|
||||
}
|
||||
.button-off {
|
||||
// background-color: #858585;
|
||||
}
|
||||
.button-off:hover {
|
||||
// background-color: #252524;
|
||||
}
|
||||
*/
|
||||
#sk-modules-table {
|
||||
border: solid thin;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
#sk-modules-table caption {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
#sk-modules-table th,
|
||||
#sk-modules-table td {
|
||||
border: solid thin;
|
||||
padding: 0.5rem 2rem;
|
||||
}
|
||||
#sk-modules-table td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#sk-modules-table th {
|
||||
font-weight: normal;
|
||||
}
|
||||
#sk-modules-table td {
|
||||
border-style: none solid;
|
||||
vertical-align: top;
|
||||
}
|
||||
#sk-modules-table th {
|
||||
padding: 0.2em;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#sk-modules-table tbody td:first-child::after {
|
||||
content: leader(". ");
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../sharpkey/webserver/css/styles.css
|
||||
1
webserver/css/styles.css
Normal file
1
webserver/css/styles.css
Normal file
@@ -0,0 +1 @@
|
||||
body { padding-bottom: 70px; }
|
||||
@@ -1 +0,0 @@
|
||||
../../sharpkey/webserver/favicon.ico
|
||||
|
Before Width: | Height: | Size: 36 B After Width: | Height: | Size: 4.2 KiB |
BIN
webserver/favicon.ico
Normal file
BIN
webserver/favicon.ico
Normal file
Binary file not shown.
|
Before Width: | Height: | Size: 36 B After Width: | Height: | Size: 4.2 KiB |
1
webserver/font-awesome/css/font-awesome.css
vendored
1
webserver/font-awesome/css/font-awesome.css
vendored
@@ -1 +0,0 @@
|
||||
../../../../sharpkey/webserver/font-awesome/css/font-awesome.css
|
||||
2337
webserver/font-awesome/css/font-awesome.css
vendored
Normal file
2337
webserver/font-awesome/css/font-awesome.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../../../../sharpkey/webserver/font-awesome/css/font-awesome.min.css
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user