Updates with the mzInterface stage

This commit is contained in:
Philip Smart
2022-01-29 22:08:21 +00:00
parent f828445b76
commit 8c5cb2fa8e
4 changed files with 331 additions and 153 deletions

View File

@@ -288,11 +288,35 @@ menu "MZ25Key Configuration"
endmenu endmenu
config DEBUG_SERIAL config MZ_DEBUG_SERIAL
bool "Serial debug output" bool "Serial debug output"
default false default false
help help
Enable debug output (non ESP logging) on the serial port. 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 endmenu
config PWRLED config PWRLED

View File

@@ -1,12 +1,12 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Name: keytable.h // Name: MZKeyTable.h
// Created: Jan 2022 // Created: Jan 2022
// Version: v1.0 // Version: v1.0
// Author(s): Philip Smart // Author(s): Philip Smart
// Description: The PS/2 Scan Code to MZ-2500/2800 Key Matrix mapping logic. // 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 // 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. // out to the MZ-2500/2800 as though it was a real keyboard.
// Credits: // Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org> // Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
@@ -52,13 +52,24 @@
// 4 G F E D C B A ? // 4 G F E D C B A ?
// 5 O N M L K J I H // 5 O N M L K J I H
// 6 W V U T S R Q P // 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 // 8 7' 6& 5% 4$ 3# 2" 1! 0
// 9 [( @ -= ;+ :* 9) 8( // 9 [( @ -= ;+ :* 9) 8(
// 10 / * ESC BACKSPACE INST/DEL CLR/HOME COPY ]} // 10 / * ESC BACKSPACE INST/DEL CLR/HOME COPY ]}
// 11 CTRL ¿¿ SHIFT LOCK GRAPH // 11 CTRL ¿¿ SHIFT LOCK GRAPH
// 12 ¿¿ ¿¿¿ // 12 ¿¿ ¿¿¿
// 13 HELP ARGO // 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_KEYPOS 0
#define PSMZTBL_SHIFTPOS 1 #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, 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 #endif // KEYTABLE_H

View File

@@ -1,12 +1,30 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Name: mz25key.ino // Name: main.cpp
// Created: Jan 2022 // Created: Jan 2022
// Version: v1.0 // Version: v1.0
// Author(s): Philip Smart // Author(s): Philip Smart
// Description: MZ2500/2800 Key Matrix logic. // Description: MZ2500/2800 Key Matrix logic.
// This source file contains the logic to transmit the virtual key matrix, which is // This source file contains the application logic to obtain PS/2 scan codes, map them
// built from PS/2 scan codes, to the MZ2500/2800. // 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: // Credits:
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org> // Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
// //
@@ -53,12 +71,37 @@
// //
// All configuration is performed via the 'idf.py menuconfig' command. // All configuration is performed via the 'idf.py menuconfig' command.
// Optionally override via the definitions below. // Optionally override via the definitions below.
// Debugging options.
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//#define CONFIG_DEBUG_OLED !CONFIG_OLED_DISABLED //#define CONFIG_DEBUG_OLED !CONFIG_OLED_DISABLED
//#define CONFIG_PWRLED 25 //#define CONFIG_PWRLED 25
//#define CONFIG_PS2_HW_DATAPIN 14 //#define CONFIG_PS2_HW_DATAPIN 14
//#define CONFIG_PS2_HW_CLKPIN 13 //#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. // 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. // Structure to manage the translated key matrix. This is updated by the ps2Interface thread and read by the mzInterface thead.
typedef struct { typedef struct {
uint8_t strobeAll; uint8_t strobeAll;
uint8_t keyMatrix[15]; uint32_t strobeAllAsGPIO;
uint8_t keyMatrix[16];
uint32_t keyMatrixAsGPIO[16];
} t_mzControl; } 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. // Instantiate base classes. First, production required objects.
PS2KeyAdvanced Keyboard; PS2KeyAdvanced Keyboard;
// Nex/t, debug required objects.
// Debug required objects.
SSD1306_t SSD1306; SSD1306_t SSD1306;
// Handle to interact with the mz-2500 interface thread. // Handle to interact with the mz-2500 interface thread.
@@ -84,20 +133,27 @@ TaskHandle_t TaskPS2IF = NULL;
static portMUX_TYPE mzMutex = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE mzMutex = portMUX_INITIALIZER_UNLOCKED;
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED) #if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
// Printf to terminal, needed when OLED is connected for debugging. // Printf to debug console terminal.
void terminalPrintf(const char * format, ...) void dbgprintf(const char * format, ...)
{ {
va_list ap; // Locals.
va_list ap;
// Commence variable argument processing.
va_start(ap, format); va_start(ap, format);
// Use vararg printf to expand and return the buffer size needed.
int size = vsnprintf(nullptr, 0, format, ap) + 1; int size = vsnprintf(nullptr, 0, format, ap) + 1;
if (size > 0) if (size > 0)
{ {
va_end(ap); va_end(ap);
// Repeat and this time output the expanded string to a buffer for printing.
va_start(ap, format); va_start(ap, format);
char buf[size + 1]; char buf[size + 1];
vsnprintf(buf, size, format, ap); vsnprintf(buf, size, format, ap);
// u8g2.print(buf);
// u8g2.sendBuffer(); // Output to LED or console
// tbc
} }
va_end(ap); 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 // can be made except for basic I/O ports. The spinlock has to be released for non
// I/O work. // 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 ) IRAM_ATTR void mz25Interface( void * pvParameters )
{ {
// Locals. // 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. // Create, initialise and hold a spinlock so the current core is bound to this one method.
portENTER_CRITICAL(&mzMutex); portENTER_CRITICAL(&mzMutex);
// Permanent loop, just wait for an RTSN strobe, latch the row, lookup matrix and output. // 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(;;) for(;;)
{ {
gpio_set_level((gpio_num_t)CONFIG_PWRLED, 1); // Turn on Power LED.
// digitalWrite(CONFIG_PWRLED, HIGH); GPIO.out_w1ts = pwrLEDMask;
for(idx=0; idx < 10000000; idx++)
// 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 // Set all required KDO bits according to keyMatrix, set state = '0'.
TIMERG0.wdt_feed=1; // feed dog GPIO.out_w1tc = mzControl.keyMatrixAsGPIO[strobeRow]; // Set to '0' active bits.
TIMERG0.wdt_wprotect=0; // write protect } else
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)
{ {
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; // write enable // Set all required KDO bits according to the strobe all value. set state = '0'.
TIMERG0.wdt_feed=1; // feed dog GPIO.out_w1tc = mzControl.strobeAllAsGPIO; // Set to '0' active bits.
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
} }
// 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. // Locals.
uint8_t idx; uint8_t idx;
uint8_t idx2; 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 // Loop through the entire conversion table to find a match on this key, if found appy the conversion to the virtual
// switch matrix. // switch matrix.
@@ -191,14 +275,17 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] |= PS2toMZ[idx][PSMZTBL_MXKEY1]; mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] |= PS2toMZ[idx][PSMZTBL_MXKEY1];
changed = 1;
} }
if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] |= PS2toMZ[idx][PSMZTBL_MXKEY2]; mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] |= PS2toMZ[idx][PSMZTBL_MXKEY2];
changed = 1;
} }
if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW3]] |= PS2toMZ[idx][PSMZTBL_MXKEY3]; mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW3]] |= PS2toMZ[idx][PSMZTBL_MXKEY3];
changed = 1;
} }
} else } else
{ {
@@ -206,27 +293,60 @@ IRAM_ATTR unsigned char updateMatrix(uint16_t data)
if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW1] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY1]; mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW1]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY1];
changed = 1;
} }
if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW2] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY2]; mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW2]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY2];
changed = 1;
} }
if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF) if(PS2toMZ[idx][PSMZTBL_MXROW3] != 0xFF)
{ {
mzControl.keyMatrix[PS2toMZ[idx][PSMZTBL_MXROW3]] &= ~PS2toMZ[idx][PSMZTBL_MXKEY3]; 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. // Only spend timw updating signals if an actual change occurred. Some keys arent valid so no change will be effected.
mzControl.strobeAll = 0xFF; if(changed)
for(idx2=0; idx2 < 15; idx2++)
{ {
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. // 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. // The PS/2 data is received via interrupt.
// //
IRAM_ATTR void ps2Interface( void * pvParameters ) IRAM_ATTR void ps2Interface( void * pvParameters )
//IRAM_ATTR void ps2Interface( )
{ {
// Locals. // Locals.
uint16_t scanCode = 0x0000; uint16_t scanCode = 0x0000;
@@ -248,9 +367,7 @@ IRAM_ATTR void ps2Interface( void * pvParameters )
#if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED) #if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
if((clrTimer > 0 && --clrTimer == 0) || ((scanCode&0xFF) == PS2_KEY_C && scanCode & PS2_BREAK )) if((clrTimer > 0 && --clrTimer == 0) || ((scanCode&0xFF) == PS2_KEY_C && scanCode & PS2_BREAK ))
{ {
// Clear old scan code data. // Clear old scan code data. Add OLED code if needed.
// u8g2.drawStr(0, 8*7, " ");
// u8g2.sendBuffer();
scanPrtCol = 0; scanPrtCol = 0;
} }
#endif #endif
@@ -265,42 +382,58 @@ IRAM_ATTR void ps2Interface( void * pvParameters )
// Clear screen as requested. // Clear screen as requested.
if(clrScreen == 1) if(clrScreen == 1)
{ {
ssd1306_clear_screen(&SSD1306, false); // ssd1306_clear_screen(&SSD1306, false);
clrScreen = 0; clrScreen = 0;
} }
// Output the scan code for verification. // Output the scan code for verification.
// u8g2.setCursor((scanPrtCol*5)*6, 8*7); dbgprintf("%04x,", scanCode);
terminalPrintf("%04x,", scanCode);
if(scanPrtCol++ >= 3) scanPrtCol = 0; if(scanPrtCol++ >= 3) scanPrtCol = 0;
// u8g2.sendBuffer();
clrTimer = 2000000; clrTimer = 2000000;
dataChange = 1;
#endif #endif
// Update the virtual matrix with the new key value. // 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) 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 idx=0; idx < 15; idx++)
{ {
for(int idx2=0; idx2 < 8; idx2++) mzControl.keyMatrixAsGPIO[idx] = (((mzControl.keyMatrix[idx] >> 7) & 0x01) ^ 0x01) << CONFIG_MZ_KDO7 |
{ (((mzControl.keyMatrix[idx] >> 6) & 0x01) ^ 0x01) << CONFIG_MZ_KDO6 |
oledBuf[idx2][idx] = ((mzControl.keyMatrix[idx] >> idx2)&0x01) == 1 ? '1' : '0'; (((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++) #if defined(CONFIG_DEBUG_OLED) || !defined(CONFIG_OLED_DISABLED)
{ // Output the MZ virtual keyboard matrix for verification.
ssd1306_display_text(&SSD1306, idx, (char *)oledBuf[idx], 15, false); 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. // Locals.
gpio_config_t io_conf; 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. // Start the keyboard, no mouse.
ESP_LOGI(tag, "Initialise PS2 keyboard."); ESP_LOGI(tag, "Initialise PS2 keyboard.");
@@ -357,69 +500,66 @@ void setup()
ssd1306_contrast(&SSD1306, 0xff); ssd1306_contrast(&SSD1306, 0xff);
#endif #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. // 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."); #if !defined(CONFIG_MZ_DISABLE_KDB)
io_conf.intr_type = GPIO_INTR_DISABLE; ESP_LOGI(tag, "Configuring MZ-2500/2800 4 bit Row Number Inputs.");
io_conf.mode = GPIO_MODE_INPUT; io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB0); io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB0);
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
gpio_config(&io_conf); io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB1); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB1);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB2); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB2);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDB3); gpio_config(&io_conf);
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."); #if !defined(CONFIG_MZ_DISABLE_KDO)
io_conf.intr_type = GPIO_INTR_DISABLE; ESP_LOGI(tag, "Configuring MZ-2500/2800 8 bit Strobe data Outputs.");
io_conf.mode = GPIO_MODE_OUTPUT; io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO0); io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO0);
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&io_conf); io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO1); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO1);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO2); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO2);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO3); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO3);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO4); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO4);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO5); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO5);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO6); gpio_config(&io_conf);
gpio_config(&io_conf); io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO6);
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDO7); gpio_config(&io_conf);
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."); #if !defined(CONFIG_MZ_DISABLE_KDI)
io_conf.intr_type = GPIO_INTR_DISABLE; ESP_LOGI(tag, "Configuring MZ-2500/2800 RTSN Input.");
io_conf.mode = GPIO_MODE_INPUT; io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_RTSNI); io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_RTSNI);
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&io_conf); io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
#endif
ESP_LOGI(tag, "Configuring MZ-2500/2800 KD4 Input."); #if !defined(CONFIG_MZ_DISABLE_RTSNI)
io_conf.intr_type = GPIO_INTR_DISABLE; ESP_LOGI(tag, "Configuring MZ-2500/2800 KD4 Input.");
io_conf.mode = GPIO_MODE_INPUT; io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDI4); io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; io_conf.pin_bit_mask = (1ULL<<CONFIG_MZ_KDI4);
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&io_conf); 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! // Check to see if keyboard available, no keyboard = no point, so halt!
// Firstly, ping keyboard to see if it is there. // 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 // 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. // to interact with the PS/2 keyboard and buffer scan codes.
// //
// Core 1 - MZ Interface
ESP_LOGI(tag, "Starting mz25if thread..."); ESP_LOGI(tag, "Starting mz25if thread...");
xTaskCreatePinnedToCore(mz25Interface, "mz25if", 32768, NULL, 25, &TaskMZ25IF, 1); xTaskCreatePinnedToCore(mz25Interface, "mz25if", 32768, NULL, 25, &TaskMZ25IF, 1);
vTaskDelay(500); vTaskDelay(500);
// Core 0 - Application
ESP_LOGI(tag, "Starting ps2if thread..."); ESP_LOGI(tag, "Starting ps2if thread...");
xTaskCreatePinnedToCore(ps2Interface, "ps2if", 32768, NULL, 22, &TaskPS2IF, 0); xTaskCreatePinnedToCore(ps2Interface, "ps2if", 32768, NULL, 22, &TaskPS2IF, 0);
vTaskDelay(500); vTaskDelay(500);
} }
// ESP-IDF Application entry point.
//
extern "C" void app_main() extern "C" void app_main()
{ {
// initArduino(); // Arduino runtime support isnt needed.
//initArduino();
// Setup hardware and start primary control threads, // Setup hardware and start primary control threads,
setup(); setup();
// Nothing to do, yield CPU.
while(1) {
vTaskDelay(10000);
}
} }

View File

@@ -149,7 +149,7 @@ CONFIG_KEYMAP_WYSE_KB3926=y
# 4Bit Strobe Input # 4Bit Strobe Input
# #
CONFIG_MZ_KDB0=23 CONFIG_MZ_KDB0=23
CONFIG_MZ_KDB1=25 CONFIG_MZ_KDB1=2
CONFIG_MZ_KDB2=26 CONFIG_MZ_KDB2=26
CONFIG_MZ_KDB3=27 CONFIG_MZ_KDB3=27
# end of 4Bit Strobe Input # end of 4Bit Strobe Input
@@ -157,14 +157,14 @@ CONFIG_MZ_KDB3=27
# #
# 8Bit Scan Data Output # 8Bit Scan Data Output
# #
CONFIG_MZ_KDO0=14 CONFIG_MZ_KDO0=7
CONFIG_MZ_KDO1=15 CONFIG_MZ_KDO1=11
CONFIG_MZ_KDO2=16 CONFIG_MZ_KDO2=12
CONFIG_MZ_KDO3=17 CONFIG_MZ_KDO3=17
CONFIG_MZ_KDO4=18 CONFIG_MZ_KDO4=18
CONFIG_MZ_KDO5=19 CONFIG_MZ_KDO5=19
CONFIG_MZ_KDO6=21 CONFIG_MZ_KDO6=21
CONFIG_MZ_KDO7=21 CONFIG_MZ_KDO7=22
# end of 8Bit Scan Data Output # end of 8Bit Scan Data Output
CONFIG_MZ_RTSNI=35 CONFIG_MZ_RTSNI=35
@@ -190,7 +190,11 @@ CONFIG_SDA_GPIO=4
CONFIG_RESET_GPIO=16 CONFIG_RESET_GPIO=16
# end of OLED # 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 # end of Debug Options
CONFIG_PWRLED=25 CONFIG_PWRLED=25
@@ -610,13 +614,13 @@ CONFIG_ESP_CONSOLE_MULTIPLE_UART=y
CONFIG_ESP_CONSOLE_UART_NUM=0 CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
CONFIG_ESP_INT_WDT=y CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 CONFIG_ESP_INT_WDT_TIMEOUT_MS=1000
CONFIG_ESP_INT_WDT_CHECK_CPU1=y # CONFIG_ESP_INT_WDT_CHECK_CPU1 is not set
CONFIG_ESP_TASK_WDT=y CONFIG_ESP_TASK_WDT=y
# CONFIG_ESP_TASK_WDT_PANIC is not set # CONFIG_ESP_TASK_WDT_PANIC is not set
CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 CONFIG_ESP_TASK_WDT_TIMEOUT_S=5
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y # CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set
# CONFIG_ESP_PANIC_HANDLER_IRAM 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_5 is not set
CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y
@@ -1409,13 +1413,13 @@ CONFIG_CONSOLE_UART=y
CONFIG_CONSOLE_UART_NUM=0 CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=115200 CONFIG_CONSOLE_UART_BAUDRATE=115200
CONFIG_INT_WDT=y CONFIG_INT_WDT=y
CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_TIMEOUT_MS=1000
CONFIG_INT_WDT_CHECK_CPU1=y # CONFIG_INT_WDT_CHECK_CPU1 is not set
CONFIG_TASK_WDT=y CONFIG_TASK_WDT=y
# CONFIG_TASK_WDT_PANIC is not set # CONFIG_TASK_WDT_PANIC is not set
CONFIG_TASK_WDT_TIMEOUT_S=5 CONFIG_TASK_WDT_TIMEOUT_S=5
CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y # CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set
CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set
CONFIG_TIMER_TASK_STACK_SIZE=3584 CONFIG_TIMER_TASK_STACK_SIZE=3584
# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set