emu48-mirror/Sources/Emu48/KEYBOARD.C

130 lines
3.7 KiB
C
Raw Normal View History

2024-03-19 22:24:30 +01:00
/*
* keyboard.c
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
*
*/
#include "pch.h"
#include "Emu48.h"
2024-03-19 22:36:03 +01:00
#include "io.h" // I/O definitions
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
static WORD Keyboard_GetIR(VOID)
2024-03-19 22:24:30 +01:00
{
WORD r = 0;
2024-03-19 22:38:33 +01:00
// OR[0:8] are wired on Clarke/Yorke chip
2024-03-19 22:24:30 +01:00
if (Chipset.out==0) return 0;
if (Chipset.out&0x001) r|=Chipset.Keyboard_Row[0];
if (Chipset.out&0x002) r|=Chipset.Keyboard_Row[1];
if (Chipset.out&0x004) r|=Chipset.Keyboard_Row[2];
if (Chipset.out&0x008) r|=Chipset.Keyboard_Row[3];
if (Chipset.out&0x010) r|=Chipset.Keyboard_Row[4];
if (Chipset.out&0x020) r|=Chipset.Keyboard_Row[5];
if (Chipset.out&0x040) r|=Chipset.Keyboard_Row[6];
if (Chipset.out&0x080) r|=Chipset.Keyboard_Row[7];
if (Chipset.out&0x100) r|=Chipset.Keyboard_Row[8];
return r;
}
2024-03-19 22:38:33 +01:00
VOID ScanKeyboard(BOOL bActive, BOOL bReset)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:38:33 +01:00
// bActive = TRUE -> function called by direct read (A=IN, C=IN, RSI)
// FALSE -> function called by 1ms keyboard poll simulation
// bReset = TRUE -> Reset Chipset.in interrupt state register
// FALSE -> generate interrupt only for new pressed keys
// keyboard read not active?
2024-03-19 22:38:33 +01:00
if (!( bActive || Chipset.Shutdn || Chipset.IR15X
|| (Chipset.intk && (Chipset.IORam[TIMER2_CTRL]&RUN) != 0)))
{
EnterCriticalSection(&csKeyLock);
{
Chipset.in &= ~0x8000; // remove ON key
}
LeaveCriticalSection(&csKeyLock);
return;
}
2024-03-19 22:24:30 +01:00
EnterCriticalSection(&csKeyLock); // synchronize
{
BOOL bKbdInt;
WORD wOldIn = Chipset.in; // save old Chipset.in state
2024-03-19 22:25:45 +01:00
UpdateKdnBit(); // update KDN bit
Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
2024-03-19 22:24:30 +01:00
2024-03-19 22:38:33 +01:00
Chipset.in = Keyboard_GetIR(); // update Chipset.in register
2024-03-19 22:36:03 +01:00
Chipset.in |= Chipset.IR15X; // add ON key
2024-03-19 22:24:30 +01:00
2024-03-19 22:38:33 +01:00
// interrupt for any new pressed keys?
2024-03-19 22:36:03 +01:00
bKbdInt = (Chipset.in && (wOldIn & 0x1FF) == 0) || Chipset.IR15X || bReset;
2024-03-19 22:24:30 +01:00
2024-03-19 22:36:03 +01:00
// update keyboard interrupt pending flag when 1ms keyboard scan is disabled
2024-03-19 22:24:30 +01:00
Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk);
2024-03-19 22:38:33 +01:00
// keyboard interrupt enabled?
bKbdInt = bKbdInt && Chipset.intk;
// interrupt at ON key pressed
bKbdInt = bKbdInt || Chipset.IR15X != 0;
// no interrupt if still inside interrupt service routine
bKbdInt = bKbdInt && Chipset.inte;
2024-03-19 22:24:30 +01:00
if (Chipset.in != 0) // any key pressed
{
if (bKbdInt) // interrupt enabled
{
Chipset.SoftInt = TRUE; // interrupt request
bInterrupt = TRUE; // exit emulation loop
}
if (Chipset.Shutdn) // cpu sleeping
2024-03-19 22:25:45 +01:00
{
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
SetEvent(hEventShutdn); // wake up emulation thread
}
2024-03-19 22:24:30 +01:00
}
else
{
2024-03-19 22:25:45 +01:00
Chipset.intd = FALSE; // no keyboard interrupt pending
2024-03-19 22:24:30 +01:00
}
}
LeaveCriticalSection(&csKeyLock);
return;
}
VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
{
2024-03-19 22:37:03 +01:00
if (nState != SM_RUN) // not in running state
2024-03-19 22:24:30 +01:00
return; // ignore key
KeyMacroRecord(bPress,out,in); // save all keyboard events
2024-03-19 22:24:30 +01:00
if (in == 0x8000) // ON key ?
{
Chipset.IR15X = bPress?0x8000:0x0000; // refresh special ON key flag
}
else
{
// "out" is outside Keyboard_Row
if (out >= ARRAYSIZEOF(Chipset.Keyboard_Row)) return;
// in &= 0x1FF; // only IR[0:8] are wired on Clarke/Yorke chip
2024-03-19 22:37:54 +01:00
_ASSERT(out < ARRAYSIZEOF(Chipset.Keyboard_Row));
2024-03-19 22:38:33 +01:00
if (bPress) // key pressed
2024-03-19 22:24:30 +01:00
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
else
Chipset.Keyboard_Row[out] &= (~in); // clear key marker in keyboard row
}
2024-03-19 22:38:33 +01:00
AdjKeySpeed(); // adjust key repeat speed
ScanKeyboard(FALSE,FALSE); // update Chipset.in register by 1ms keyboard poll
2024-03-19 22:25:45 +01:00
Sleep(50); // hold key state for a definite time
2024-03-19 22:24:30 +01:00
return;
}