Updates with the mzInterface stage
This commit is contained in:
@@ -288,11 +288,35 @@ menu "MZ25Key Configuration"
|
||||
|
||||
endmenu
|
||||
|
||||
config DEBUG_SERIAL
|
||||
config MZ_DEBUG_SERIAL
|
||||
bool "Serial debug output"
|
||||
default false
|
||||
help
|
||||
Enable debug output (non ESP logging) on the serial port.
|
||||
|
||||
config MZ_DISABLE_KDB
|
||||
bool "Disable input mode actuation of the KDB data bus"
|
||||
default false
|
||||
help
|
||||
Disable the MZ Interface KDB input configuration step, useful feature for debugging.
|
||||
|
||||
config MZ_DISABLE_KDO
|
||||
bool "Disable output mode actuation of the KDO strobe row"
|
||||
default false
|
||||
help
|
||||
Disable the MZ Interface KDO output configuration step, useful feature for debugging.
|
||||
|
||||
config MZ_DISABLE_RTSNI
|
||||
bool "Disable input mode actuation of the RTSNi signal"
|
||||
default false
|
||||
help
|
||||
Disable the MZ Interface RTSNi input configuration step, useful feature for debugging.
|
||||
|
||||
config MZ_DISABLE_KDI
|
||||
bool "Disable input mode actuation of the KDI4 signal"
|
||||
default false
|
||||
help
|
||||
Disable the MZ Interface KDI input configuration step, useful feature for debugging.
|
||||
endmenu
|
||||
|
||||
config PWRLED
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: keytable.h
|
||||
// Name: MZKeyTable.h
|
||||
// Created: Jan 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: The PS/2 Scan Code to MZ-2500/2800 Key Matrix mapping logic.
|
||||
// This source file contains the definitions and tables to convert a PS/2 scan code
|
||||
// into an MZ 13x8 matrix equivalent for the received key. The matrix is then read
|
||||
// into an MZ 14x8 matrix equivalent for the received key. The matrix is then read
|
||||
// out to the MZ-2500/2800 as though it was a real keyboard.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||
@@ -52,13 +52,24 @@
|
||||
// 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 <¿ .>¿ ¿¿ ¿ | '¿ Z ¿ Y X ¿
|
||||
// 7 <¿ .>¿ ¿¿ ¿ | '¿ Z ¿ Y X ¿
|
||||
// 8 7' 6& 5% 4$ 3# 2" 1! 0
|
||||
// 9 [( @ -= ;+ :* 9) 8(
|
||||
// 10 / * ESC BACKSPACE INST/DEL CLR/HOME COPY ]}
|
||||
// 11 CTRL ¿¿ SHIFT LOCK GRAPH
|
||||
// 12 ¿¿ ¿¿¿
|
||||
// 11 CTRL ¿¿ SHIFT LOCK GRAPH
|
||||
// 12 ¿¿ ¿¿¿
|
||||
// 13 HELP ARGO
|
||||
//
|
||||
// Col 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
// --------------------------------------------------------------------------------------------------------------------------------------
|
||||
// D0 F1 F9 0 TAB ? H P 0 8( ]} GRAPH ¿¿¿ ARGO
|
||||
// D1 F2 F10 1 SPACE A I Q T 1! 9) COPY LOCK ¿¿ HELP
|
||||
// D2 F3 8 2 RETURN B J R Z ¿ 2" :* CLR/HOME SHIFT
|
||||
// D3 F4 9 3 UP C K S | '¿ 3# ;+ INST/DEL ¿¿
|
||||
// D4 F5 , 4 DOWN D L T ¿ 4$ -= BACKSPACE CTRL
|
||||
// D5 F6 . 5 LEFT E M U ¿¿ 5% @ ESC
|
||||
// D6 F7 + 6 RIGHT F N V .>¿ 6& [( *
|
||||
// D7 F8 - 7 BREAK G O W <¿ 7' /
|
||||
|
||||
#define PSMZTBL_KEYPOS 0
|
||||
#define PSMZTBL_SHIFTPOS 1
|
||||
@@ -183,7 +194,4 @@ const unsigned char PS2toMZ[][PSMZTBL_MAXROWS] =
|
||||
0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
// PS/2 BREAK key code string
|
||||
const unsigned char BREAK_CODE[8]={0xE1,0x14,0x77,0xE1,0xF0,0x14,0xF0,0x77};
|
||||
|
||||
#endif // KEYTABLE_H
|
||||
|
||||
402
main/main.cpp
402
main/main.cpp
@@ -1,12 +1,30 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: mz25key.ino
|
||||
// Name: main.cpp
|
||||
// Created: Jan 2022
|
||||
// Version: v1.0
|
||||
// Author(s): Philip Smart
|
||||
// Description: MZ2500/2800 Key Matrix logic.
|
||||
// This source file contains the logic to transmit the virtual key matrix, which is
|
||||
// built from PS/2 scan codes, to the MZ2500/2800.
|
||||
// This source file contains the application logic to obtain PS/2 scan codes, map them
|
||||
// into a virtual keyboard matrix as per the Sharp MZ series key matrix and the
|
||||
// logic to transmit the virtual key matrix to the MZ2500/2800.
|
||||
//
|
||||
// The application uses a modified version of the PS2KeyAdvanced
|
||||
// https://github.com/techpaul/PS2KeyAdvanced class from Paul Carpenter.
|
||||
//
|
||||
// The application uses, for debug purposes, the esp-idf-ssd1306 class from nopnop2002
|
||||
// https://github.com/nopnop2002/esp-idf-ssd1306.
|
||||
//
|
||||
// The application uses the Espressif Development environment with Arduino components.
|
||||
// This is necessary for the PS2KeyAdvanced class, which I may in future convert to
|
||||
// use esp-idf library calls rather than Arduino.
|
||||
//
|
||||
// The Espressif environment is necessary in order to have more control over the build.
|
||||
// It is important, for timing, that the Core 1 is dedicated to MZ Interface
|
||||
// logic and Core 0 is used for all RTOS/Interrupts tasks.
|
||||
//
|
||||
// The application is configured via the Kconfig system. Use idf.py menuconfig to
|
||||
// configure.
|
||||
// Credits:
|
||||
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
@@ -53,12 +71,37 @@
|
||||
//
|
||||
// All configuration is performed via the 'idf.py menuconfig' command.
|
||||
// Optionally override via the definitions below.
|
||||
// Debugging options.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//#define CONFIG_DEBUG_OLED !CONFIG_OLED_DISABLED
|
||||
//#define CONFIG_PWRLED 25
|
||||
//#define CONFIG_PS2_HW_DATAPIN 14
|
||||
//#define CONFIG_PS2_HW_CLKPIN 13
|
||||
//#define CONFIG_KEYMAP_WYSE_KB3926
|
||||
//#define CONFIG_KEYMAP_STANDARD
|
||||
//#define CONFIG_MZ_KDB0 23
|
||||
//#define CONFIG_MZ_KDB1 25
|
||||
//#define CONFIG_MZ_KDB2 26
|
||||
//#define CONFIG_MZ_KDB3 27
|
||||
//#define CONFIG_MZ_KDO0 14
|
||||
//#define CONFIG_MZ_KDO1 15
|
||||
//#define CONFIG_MZ_KDO2 16
|
||||
//#define CONFIG_MZ_KDO3 17
|
||||
//#define CONFIG_MZ_KDO4 18
|
||||
//#define CONFIG_MZ_KDO5 19
|
||||
//#define CONFIG_MZ_KDO6 21
|
||||
//#define CONFIG_MZ_KDO7 21
|
||||
//#define CONFIG_MZ_RTSNI 35
|
||||
//#define CONFIG_MZ_KDI4 13
|
||||
//#CONFIG_OLED_DISABLED
|
||||
//#CONFIG_I2C_INTERFACE
|
||||
//#CONFIG_SPI_INTERFACE
|
||||
//#CONFIG_SSD1306_128x32
|
||||
//#CONFIG_SSD1306_128x64
|
||||
//#CONFIG_OFFSETX 0
|
||||
//#CONFIG_FLIP
|
||||
//#CONFIG_SCL_GPIO 5
|
||||
//#CONFIG_SDA_GPIO 4
|
||||
//#CONFIG_RESET_GPIO 16
|
||||
|
||||
// Macros.
|
||||
//
|
||||
@@ -67,13 +110,19 @@
|
||||
// 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;
|
||||
uint8_t keyMatrix[15];
|
||||
uint32_t strobeAllAsGPIO;
|
||||
uint8_t keyMatrix[16];
|
||||
uint32_t keyMatrixAsGPIO[16];
|
||||
} t_mzControl;
|
||||
volatile t_mzControl mzControl = { 0xFF, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
|
||||
volatile t_mzControl mzControl = { 0xFF, 0x00000000,
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
// Instantiate base classes. First, production required objects.
|
||||
PS2KeyAdvanced Keyboard;
|
||||
// Nex/t, debug required objects.
|
||||
|
||||
// Debug required objects.
|
||||
SSD1306_t SSD1306;
|
||||
|
||||
// Handle to interact with the mz-2500 interface thread.
|
||||
@@ -84,20 +133,27 @@ TaskHandle_t TaskPS2IF = NULL;
|
||||
static portMUX_TYPE mzMutex = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
|
||||
// Printf to terminal, needed when OLED is connected for debugging.
|
||||
void terminalPrintf(const char * format, ...)
|
||||
// Printf to debug console terminal.
|
||||
void dbgprintf(const char * format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
// Locals.
|
||||
va_list ap;
|
||||
|
||||
// Commence variable argument processing.
|
||||
va_start(ap, format);
|
||||
// Use vararg printf to expand and return the buffer size needed.
|
||||
int size = vsnprintf(nullptr, 0, format, ap) + 1;
|
||||
if (size > 0)
|
||||
{
|
||||
va_end(ap);
|
||||
|
||||
// Repeat and this time output the expanded string to a buffer for printing.
|
||||
va_start(ap, format);
|
||||
char buf[size + 1];
|
||||
vsnprintf(buf, size, format, ap);
|
||||
// u8g2.print(buf);
|
||||
// u8g2.sendBuffer();
|
||||
|
||||
// Output to LED or console
|
||||
// tbc
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
@@ -118,45 +174,72 @@ void terminalPrintf(const char * format, ...)
|
||||
// can be made except for basic I/O ports. The spinlock has to be released for non
|
||||
// I/O work.
|
||||
//
|
||||
// The MZ timing period is ~600ns RTSN Low to High (Latch Row data coming from MZ machine),
|
||||
// MPX (connected direct to external Quad 2-1 Mux goes high as RTSN goes low, the MPX
|
||||
// signal is held high for 300ns then goes low for 300ns. The period when RTSN is low is
|
||||
// when the MZ machine reads the scan row data. The cycle is ~1.2uS repeating, 14 rows
|
||||
// so ~16.8uS for one full key matrix, The MZ machine if stuck in a tight loop will take
|
||||
// approx 100uS to scan the matrix so the Gate Arrays are over sampling 6 times.
|
||||
//
|
||||
IRAM_ATTR void mz25Interface( void * pvParameters )
|
||||
{
|
||||
// Locals.
|
||||
volatile unsigned long idx;
|
||||
volatile uint32_t gpioIN;
|
||||
volatile uint8_t strobeRow = 0;
|
||||
uint32_t rowBitMask = (1 << CONFIG_MZ_KDB3) | (1 << CONFIG_MZ_KDB2) | (1 << CONFIG_MZ_KDB1) | (1 << CONFIG_MZ_KDB0);
|
||||
uint32_t colBitMask = (1 << CONFIG_MZ_KDO7) | (1 << CONFIG_MZ_KDO6) | (1 << CONFIG_MZ_KDO5) | (1 << CONFIG_MZ_KDO4) |
|
||||
(1 << CONFIG_MZ_KDO3) | (1 << CONFIG_MZ_KDO2) | (1 << CONFIG_MZ_KDO1) | (1 << CONFIG_MZ_KDO0);
|
||||
uint32_t pwrLEDMask = (1 << CONFIG_PWRLED);
|
||||
|
||||
ESP_LOGI(tag, "Starting mz25Interface thread, colBitMask=%08x, rowBitMask=%08x.", colBitMask, rowBitMask);
|
||||
|
||||
// Create, initialise and hold a spinlock so the current core is bound to this one method.
|
||||
portENTER_CRITICAL(&mzMutex);
|
||||
|
||||
// Permanent loop, just wait for an RTSN strobe, latch the row, lookup matrix and output.
|
||||
// Timings with Power LED = LED Off to On = 108ns, LED On to Off = 392ns
|
||||
for(;;)
|
||||
{
|
||||
gpio_set_level((gpio_num_t)CONFIG_PWRLED, 1);
|
||||
// digitalWrite(CONFIG_PWRLED, HIGH);
|
||||
for(idx=0; idx < 10000000; idx++)
|
||||
// Turn on Power LED.
|
||||
GPIO.out_w1ts = pwrLEDMask;
|
||||
|
||||
// Read the GPIO ports to get latest RTSNi and KDI4 states.
|
||||
gpioIN = REG_READ(GPIO_IN_REG);
|
||||
|
||||
// Detect RTSN going high, the MZ will send the required row during this cycle.
|
||||
if(gpioIN & CONFIG_MZ_RTSNI)
|
||||
{
|
||||
if(idx % 1000 == 0)
|
||||
// Assemble the required matrix row from the configured bits.
|
||||
strobeRow = (gpioIN >> (CONFIG_MZ_KDB3-3)) | (gpioIN >> (CONFIG_MZ_KDB2-2)) | (gpioIN >> (CONFIG_MZ_KDB1-1)) | (gpioIN >> CONFIG_MZ_KDB0);
|
||||
|
||||
// Clear all KDO bits - clear state = '1'
|
||||
GPIO.out_w1ts = colBitMask; // Reset all scan data bits to '1', inactive.
|
||||
|
||||
// KDI4 indicates if row data is needed or a single byte ANDing all the keys together, ie. to detect a key press without strobing all rows.
|
||||
if(gpioIN & CONFIG_MZ_KDI4)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
// digitalWrite(CONFIG_PWRLED, LOW);
|
||||
gpio_set_level((gpio_num_t)CONFIG_PWRLED, 0);
|
||||
for(idx=0; idx < 10000000; idx++)
|
||||
{
|
||||
if(idx % 1000 == 0)
|
||||
// Set all required KDO bits according to keyMatrix, set state = '0'.
|
||||
GPIO.out_w1tc = mzControl.keyMatrixAsGPIO[strobeRow]; // Set to '0' active bits.
|
||||
} else
|
||||
{
|
||||
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
|
||||
// Set all required KDO bits according to the strobe all value. set state = '0'.
|
||||
GPIO.out_w1tc = mzControl.strobeAllAsGPIO; // Set to '0' active bits.
|
||||
}
|
||||
|
||||
// Wait for RTSN to go low.
|
||||
while(REG_READ(GPIO_IN_REG) & CONFIG_MZ_RTSNI);
|
||||
}
|
||||
|
||||
// Turn off Power LED.
|
||||
GPIO.out_w1tc = pwrLEDMask;
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +250,7 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
|
||||
// Locals.
|
||||
uint8_t idx;
|
||||
uint8_t idx2;
|
||||
uint8_t changed = 0;
|
||||
|
||||
// Loop through the entire conversion table to find a match on this key, if found appy the conversion to the virtual
|
||||
// switch matrix.
|
||||
@@ -191,14 +275,17 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] |= PS2toMZ[idx][PSMZTBL_MXKEY1];
|
||||
changed = 1;
|
||||
}
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] |= PS2toMZ[idx][PSMZTBL_MXKEY2];
|
||||
changed = 1;
|
||||
}
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW3]] |= PS2toMZ[idx][PSMZTBL_MXKEY3];
|
||||
changed = 1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -206,27 +293,60 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY1];
|
||||
changed = 1;
|
||||
}
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY2];
|
||||
changed = 1;
|
||||
}
|
||||
if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF)
|
||||
{
|
||||
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW3]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY3];
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-calculate the Strobe All (KD4 = 1) signal, this indicates if any bit (key) in the matrix is active.
|
||||
mzControl.strobeAll = 0xFF;
|
||||
for(idx2=0; idx2 < 15; idx2++)
|
||||
|
||||
// Only spend timw updating signals if an actual change occurred. Some keys arent valid so no change will be effected.
|
||||
if(changed)
|
||||
{
|
||||
mzControl.strobeAll &= mzControl.keyMatrix[idx2];
|
||||
// To save time in the MZ Interface, a mirror keyMatrix is built up, 32bit (GPIO Bank 0) wide, with the keyMatrix 8 bit data
|
||||
// mapped onto the configured pins in the 32bit register. This saves previous time in order to meet the tight 1.2uS cycle.
|
||||
//
|
||||
for(int idx=0; idx < 15; idx++)
|
||||
{
|
||||
mzControl.keyMatrixAsGPIO[idx] = (((mzControl.keyMatrix[idx] >> 7) & 0x01) ^ 0x01) << CONFIG_MZ_KDO7 |
|
||||
(((mzControl.keyMatrix[idx] >> 6) & 0x01) ^ 0x01) << CONFIG_MZ_KDO6 |
|
||||
(((mzControl.keyMatrix[idx] >> 5) & 0x01) ^ 0x01) << CONFIG_MZ_KDO5 |
|
||||
(((mzControl.keyMatrix[idx] >> 4) & 0x01) ^ 0x01) << CONFIG_MZ_KDO4 |
|
||||
(((mzControl.keyMatrix[idx] >> 3) & 0x01) ^ 0x01) << CONFIG_MZ_KDO3 |
|
||||
(((mzControl.keyMatrix[idx] >> 2) & 0x01) ^ 0x01) << CONFIG_MZ_KDO2 |
|
||||
(((mzControl.keyMatrix[idx] >> 1) & 0x01) ^ 0x01) << CONFIG_MZ_KDO1 |
|
||||
(((mzControl.keyMatrix[idx] ) & 0x01) ^ 0x01) << CONFIG_MZ_KDO0 ;
|
||||
}
|
||||
|
||||
// Re-calculate the Strobe All (KD4 = 1) signal, this indicates if any bit (key) in the matrix is active.
|
||||
mzControl.strobeAll = 0xFF;
|
||||
mzControl.strobeAllAsGPIO = 0x00000000;
|
||||
for(idx2=0; idx2 < 15; idx2++)
|
||||
{
|
||||
mzControl.strobeAll &= mzControl.keyMatrix[idx2];
|
||||
}
|
||||
|
||||
// To speed up the mzInterface logic, pre-calculate the strobeAll value as a 32bit GPIO output value.
|
||||
mzControl.strobeAllAsGPIO |= (((mzControl.strobeAll >> 7) & 0x01) ^ 0x01) << CONFIG_MZ_KDO7 |
|
||||
(((mzControl.strobeAll >> 6) & 0x01) ^ 0x01) << CONFIG_MZ_KDO6 |
|
||||
(((mzControl.strobeAll >> 5) & 0x01) ^ 0x01) << CONFIG_MZ_KDO5 |
|
||||
(((mzControl.strobeAll >> 4) & 0x01) ^ 0x01) << CONFIG_MZ_KDO4 |
|
||||
(((mzControl.strobeAll >> 3) & 0x01) ^ 0x01) << CONFIG_MZ_KDO3 |
|
||||
(((mzControl.strobeAll >> 2) & 0x01) ^ 0x01) << CONFIG_MZ_KDO2 |
|
||||
(((mzControl.strobeAll >> 1) & 0x01) ^ 0x01) << CONFIG_MZ_KDO1 |
|
||||
(((mzControl.strobeAll ) & 0x01) ^ 0x01) << CONFIG_MZ_KDO0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Primary PS/2 thread, running on Core 1.
|
||||
@@ -234,7 +354,6 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
|
||||
// The PS/2 data is received via interrupt.
|
||||
//
|
||||
IRAM_ATTR void ps2Interface( void * pvParameters )
|
||||
//IRAM_ATTR void ps2Interface( )
|
||||
{
|
||||
// Locals.
|
||||
uint16_t scanCode = 0x0000;
|
||||
@@ -248,9 +367,7 @@ IRAM_ATTR void ps2Interface( void * pvParameters )
|
||||
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
|
||||
if((clrTimer > 0 && --clrTimer == 0) || ((scanCode&0xFF) == PS2_KEY_C && scanCode & PS2_BREAK ))
|
||||
{
|
||||
// Clear old scan code data.
|
||||
// u8g2.drawStr(0, 8*7, " ");
|
||||
// u8g2.sendBuffer();
|
||||
// Clear old scan code data. Add OLED code if needed.
|
||||
scanPrtCol = 0;
|
||||
}
|
||||
#endif
|
||||
@@ -265,42 +382,58 @@ IRAM_ATTR void ps2Interface( void * pvParameters )
|
||||
// Clear screen as requested.
|
||||
if(clrScreen == 1)
|
||||
{
|
||||
ssd1306_clear_screen(&SSD1306, false);
|
||||
// ssd1306_clear_screen(&SSD1306, false);
|
||||
clrScreen = 0;
|
||||
}
|
||||
|
||||
// Output the scan code for verification.
|
||||
// u8g2.setCursor((scanPrtCol*5)*6, 8*7);
|
||||
terminalPrintf("%04x,", scanCode);
|
||||
dbgprintf("%04x,", scanCode);
|
||||
if(scanPrtCol++ >= 3) scanPrtCol = 0;
|
||||
// u8g2.sendBuffer();
|
||||
clrTimer = 2000000;
|
||||
dataChange = 1;
|
||||
#endif
|
||||
|
||||
// Update the virtual matrix with the new key value.
|
||||
updateMatrix(scanCode);
|
||||
}
|
||||
dataChange = updateMatrix(scanCode);
|
||||
|
||||
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
|
||||
// Output the MZ virtual keyboard matrix for verification.
|
||||
uint8_t oledBuf[8][16];
|
||||
if(dataChange)
|
||||
{
|
||||
// To save time in the MZ Interface, a mirror keyMatrix is built up, 32bit (GPIO Bank 0) wide, with the keyMatrix 8 bit data
|
||||
// mapped onto the configured pins in the 32bit register. This saves previous time in order to meet the tight 1.2uS cycle.
|
||||
//
|
||||
for(int idx=0; idx < 15; idx++)
|
||||
{
|
||||
for(int idx2=0; idx2 < 8; idx2++)
|
||||
{
|
||||
oledBuf[idx2][idx] = ((mzControl.keyMatrix[idx] >> idx2)&0x01) == 1 ? '1' : '0';
|
||||
}
|
||||
mzControl.keyMatrixAsGPIO[idx] = (((mzControl.keyMatrix[idx] >> 7) & 0x01) ^ 0x01) << CONFIG_MZ_KDO7 |
|
||||
(((mzControl.keyMatrix[idx] >> 6) & 0x01) ^ 0x01) << CONFIG_MZ_KDO6 |
|
||||
(((mzControl.keyMatrix[idx] >> 5) & 0x01) ^ 0x01) << CONFIG_MZ_KDO5 |
|
||||
(((mzControl.keyMatrix[idx] >> 4) & 0x01) ^ 0x01) << CONFIG_MZ_KDO4 |
|
||||
(((mzControl.keyMatrix[idx] >> 3) & 0x01) ^ 0x01) << CONFIG_MZ_KDO3 |
|
||||
(((mzControl.keyMatrix[idx] >> 2) & 0x01) ^ 0x01) << CONFIG_MZ_KDO2 |
|
||||
(((mzControl.keyMatrix[idx] >> 1) & 0x01) ^ 0x01) << CONFIG_MZ_KDO1 |
|
||||
(((mzControl.keyMatrix[idx] ) & 0x01) ^ 0x01) << CONFIG_MZ_KDO0 ;
|
||||
}
|
||||
|
||||
for(int idx=0; idx < 8; idx++)
|
||||
{
|
||||
ssd1306_display_text(&SSD1306, idx, (char *)oledBuf[idx], 15, false);
|
||||
}
|
||||
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
|
||||
// Output the MZ virtual keyboard matrix for verification.
|
||||
uint8_t oledBuf[8][16];
|
||||
for(int idx=0; idx < 15; idx++)
|
||||
{
|
||||
for(int idx2=0; idx2 < 8; idx2++)
|
||||
{
|
||||
oledBuf[idx2][idx] = ((mzControl.keyMatrix[idx] >> idx2)&0x01) == 1 ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
// Print out the matrix, transposed - see MZKeyTable.h for the map, second table.
|
||||
for(int idx=0; idx < 8; idx++)
|
||||
{
|
||||
ssd1306_display_text(&SSD1306, idx, (char *)oledBuf[idx], 15, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Let other tasks run.
|
||||
vTaskDelay(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +452,16 @@ void setup()
|
||||
{
|
||||
// Locals.
|
||||
gpio_config_t io_conf;
|
||||
|
||||
// Setup power LED first to show life.
|
||||
ESP_LOGI(tag, "Configuring Power LED.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_PWRLED);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level((gpio_num_t)CONFIG_PWRLED, 1);
|
||||
|
||||
// Start the keyboard, no mouse.
|
||||
ESP_LOGI(tag, "Initialise PS2 keyboard.");
|
||||
@@ -357,69 +500,66 @@ void setup()
|
||||
ssd1306_contrast(&SSD1306, 0xff);
|
||||
#endif
|
||||
|
||||
// Setup power LED.
|
||||
//pinMode(CONFIG_PWRLED, OUTPUT);
|
||||
//#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
|
||||
ESP_LOGI(tag, "Configuring Power LED.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_PWRLED);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&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.
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 4 bit Row Number Inputs.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB0);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB1);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB2);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB3);
|
||||
gpio_config(&io_conf);
|
||||
#if !defined(CONFIG_MZ_DISABLE_KDB)
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 4 bit Row Number Inputs.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB0);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB1);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB2);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB3);
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 8 bit Strobe data Outputs.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO0);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO1);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO2);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO3);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO4);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO5);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO6);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO7);
|
||||
gpio_config(&io_conf);
|
||||
#if !defined(CONFIG_MZ_DISABLE_KDO)
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 8 bit Strobe data Outputs.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO0);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO1);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO2);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO3);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO4);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO5);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO6);
|
||||
gpio_config(&io_conf);
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO7);
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 RTSN Input.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_RTSNI);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
#if !defined(CONFIG_MZ_DISABLE_KDI)
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 RTSN Input.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_RTSNI);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 KD4 Input.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDI4);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
#if !defined(CONFIG_MZ_DISABLE_RTSNI)
|
||||
ESP_LOGI(tag, "Configuring MZ-2500/2800 KD4 Input.");
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDI4);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
#endif
|
||||
|
||||
// Check to see if keyboard available, no keyboard = no point, so halt!
|
||||
// Firstly, ping keyboard to see if it is there.
|
||||
@@ -441,22 +581,24 @@ void setup()
|
||||
// all other tasks running on Core 1 will suspend. The PS/2 controller, running on the ULP processor will continue
|
||||
// to interact with the PS/2 keyboard and buffer scan codes.
|
||||
//
|
||||
// Core 1 - MZ Interface
|
||||
ESP_LOGI(tag, "Starting mz25if thread...");
|
||||
xTaskCreatePinnedToCore(mz25Interface, "mz25if", 32768, NULL, 25, &TaskMZ25IF, 1);
|
||||
vTaskDelay(500);
|
||||
|
||||
// Core 0 - Application
|
||||
ESP_LOGI(tag, "Starting ps2if thread...");
|
||||
xTaskCreatePinnedToCore(ps2Interface, "ps2if", 32768, NULL, 22, &TaskPS2IF, 0);
|
||||
vTaskDelay(500);
|
||||
}
|
||||
|
||||
// ESP-IDF Application entry point.
|
||||
//
|
||||
extern "C" void app_main()
|
||||
{
|
||||
// initArduino();
|
||||
// Arduino runtime support isnt needed.
|
||||
//initArduino();
|
||||
|
||||
// Setup hardware and start primary control threads,
|
||||
setup();
|
||||
|
||||
// Nothing to do, yield CPU.
|
||||
while(1) {
|
||||
vTaskDelay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
32
sdkconfig
32
sdkconfig
@@ -149,7 +149,7 @@ CONFIG_KEYMAP_WYSE_KB3926=y
|
||||
# 4Bit Strobe Input
|
||||
#
|
||||
CONFIG_MZ_KDB0=23
|
||||
CONFIG_MZ_KDB1=25
|
||||
CONFIG_MZ_KDB1=2
|
||||
CONFIG_MZ_KDB2=26
|
||||
CONFIG_MZ_KDB3=27
|
||||
# end of 4Bit Strobe Input
|
||||
@@ -157,14 +157,14 @@ CONFIG_MZ_KDB3=27
|
||||
#
|
||||
# 8Bit Scan Data Output
|
||||
#
|
||||
CONFIG_MZ_KDO0=14
|
||||
CONFIG_MZ_KDO1=15
|
||||
CONFIG_MZ_KDO2=16
|
||||
CONFIG_MZ_KDO0=7
|
||||
CONFIG_MZ_KDO1=11
|
||||
CONFIG_MZ_KDO2=12
|
||||
CONFIG_MZ_KDO3=17
|
||||
CONFIG_MZ_KDO4=18
|
||||
CONFIG_MZ_KDO5=19
|
||||
CONFIG_MZ_KDO6=21
|
||||
CONFIG_MZ_KDO7=21
|
||||
CONFIG_MZ_KDO7=22
|
||||
# end of 8Bit Scan Data Output
|
||||
|
||||
CONFIG_MZ_RTSNI=35
|
||||
@@ -190,7 +190,11 @@ CONFIG_SDA_GPIO=4
|
||||
CONFIG_RESET_GPIO=16
|
||||
# end of OLED
|
||||
|
||||
# CONFIG_DEBUG_SERIAL is not set
|
||||
# CONFIG_MZ_DEBUG_SERIAL is not set
|
||||
# CONFIG_MZ_DISABLE_KDB is not set
|
||||
CONFIG_MZ_DISABLE_KDO=y
|
||||
# CONFIG_MZ_DISABLE_RTSNI is not set
|
||||
# CONFIG_MZ_DISABLE_KDI is not set
|
||||
# end of Debug Options
|
||||
|
||||
CONFIG_PWRLED=25
|
||||
@@ -610,13 +614,13 @@ CONFIG_ESP_CONSOLE_MULTIPLE_UART=y
|
||||
CONFIG_ESP_CONSOLE_UART_NUM=0
|
||||
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
|
||||
CONFIG_ESP_INT_WDT=y
|
||||
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
|
||||
CONFIG_ESP_INT_WDT_CHECK_CPU1=y
|
||||
CONFIG_ESP_INT_WDT_TIMEOUT_MS=1000
|
||||
# CONFIG_ESP_INT_WDT_CHECK_CPU1 is not set
|
||||
CONFIG_ESP_TASK_WDT=y
|
||||
# CONFIG_ESP_TASK_WDT_PANIC is not set
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S=5
|
||||
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
|
||||
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
|
||||
# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set
|
||||
# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set
|
||||
# CONFIG_ESP_PANIC_HANDLER_IRAM is not set
|
||||
# CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set
|
||||
CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y
|
||||
@@ -1409,13 +1413,13 @@ CONFIG_CONSOLE_UART=y
|
||||
CONFIG_CONSOLE_UART_NUM=0
|
||||
CONFIG_CONSOLE_UART_BAUDRATE=115200
|
||||
CONFIG_INT_WDT=y
|
||||
CONFIG_INT_WDT_TIMEOUT_MS=300
|
||||
CONFIG_INT_WDT_CHECK_CPU1=y
|
||||
CONFIG_INT_WDT_TIMEOUT_MS=1000
|
||||
# CONFIG_INT_WDT_CHECK_CPU1 is not set
|
||||
CONFIG_TASK_WDT=y
|
||||
# CONFIG_TASK_WDT_PANIC is not set
|
||||
CONFIG_TASK_WDT_TIMEOUT_S=5
|
||||
CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
|
||||
CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
|
||||
# CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set
|
||||
# CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set
|
||||
CONFIG_TIMER_TASK_STACK_SIZE=3584
|
||||
# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
|
||||
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
|
||||
|
||||
Reference in New Issue
Block a user